@ -1,91 +1,114 @@
# include "funding.h"
# include "funding.h"
# include <assert.h>
# include <assert.h>
# include <string.h>
bool funding_delta ( const OpenChannel * a ,
static bool is_funder ( const OpenChannel * o )
const OpenChannel * b ,
const OpenAnchor * anchor ,
uint64_t fee ,
uint64_t * channel_delta ,
int64_t delta_a_to_b ,
uint64_t * a_amount ,
uint64_t * b_amount )
{
{
uint64_t * funder_amount , * non_funder_amount , new_delta ;
return o - > anch = = OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR ;
int64_t delta_to_funder ;
}
uint64_t funder_fee , non_funder_fee ;
assert ( * channel_delta < = anchor - > amount ) ;
if ( a - > anch = = OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR ) {
if ( b - > anch ! = OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR )
return false ;
funder_amount = a_amount ;
non_funder_amount = b_amount ;
delta_to_funder = delta_a_to_b ;
} else {
if ( a - > anch ! = OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR )
return false ;
if ( b - > anch ! = OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR )
return false ;
funder_amount = b_amount ;
non_funder_amount = a_amount ;
delta_to_funder = - delta_a_to_b ;
}
/* Trying to spend more than non-funder has? */
if ( delta_to_funder > 0 ) {
if ( delta_to_funder > * channel_delta )
return false ;
/* Trying to spend more than funder has? */
} else if ( - delta_to_funder > anchor - > amount - * channel_delta )
return false ;
new_delta = * channel_delta - delta_to_funder ;
* funder_amount = anchor - > amount - new_delta ;
* non_funder_amount = new_delta ;
/* We try to split fee. */
static bool subtract_fees ( uint64_t * funder , uint64_t * non_funder ,
funder_fee = fee / 2 ;
uint64_t * funder_fee , uint64_t * non_funder_fee ,
/* Funder gets any 1 satoshi rounding benefit! */
bool non_funder_paying , uint64_t fee )
non_funder_fee = fee - funder_fee ;
{
/* Funder gets 1 satsoshi rounding benefit! */
* non_funder_fee = fee - fee / 2 ;
if ( * non_funder_amount < non_funder_fee ) {
if ( * non_funder < * non_funder_fee ) {
/*
/*
* This happens initially , as funder has all the money .
* This happens initially , as funder has all the money .
* That ' s OK , but don ' t let non - funder withdraw if they can ' t
* That ' s OK , but don ' t let non - funder spend if they can ' t
* cover fee .
* cover fee .
*/
*/
if ( delta_to_funder > 0 )
if ( non_funder_paying )
return false ;
return false ;
/* Pay everything they can, funder pays rest. */
/* Pay everything they can, funder pays rest. */
non_funder_fee = * non_funder_amount ;
* non_funder_fee = * non_funder ;
funder_fee = fee - non_funder_fee ;
}
}
/* Funder must always ensure they can pay their share. */
/* Funder must always ensure they can pay their share. */
if ( * funder_amount < funder_fee )
* funder_fee = fee - * non_funder_fee ;
if ( * funder < * funder_fee )
return false ;
* non_funder - = * non_funder_fee ;
* funder - = * funder_fee ;
return true ;
}
bool funding_delta ( const OpenChannel * oa ,
const OpenChannel * ob ,
const OpenAnchor * anchor ,
int64_t delta_a ,
struct channel_oneside * a_side ,
struct channel_oneside * b_side )
{
uint64_t a , b , a_fee , b_fee ;
uint64_t fee ;
bool got_fees ;
a = a_side - > pay + a_side - > fee ;
b = b_side - > pay + b_side - > fee ;
fee = a_side - > fee + b_side - > fee ;
assert ( a + b = = anchor - > amount ) ;
/* Only one can be funder. */
if ( is_funder ( oa ) = = is_funder ( ob ) )
return false ;
return false ;
* funder_amount - = funder_fee ;
/* Transferring more than we have? */
* non_funder_amount - = non_funder_fee ;
if ( delta_a > 0 & & delta_a > b )
return false ;
if ( delta_a < 0 & & - delta_a > a )
return false ;
/* Adjust amounts. */
a + = delta_a ;
b - = delta_a ;
/* Now we know we're succeeding, update caller's channel_delta */
/* Take off fee from both parties if possible. */
* channel_delta = new_delta ;
if ( is_funder ( oa ) )
got_fees = subtract_fees ( & a , & b , & a_fee , & b_fee ,
delta_a > 0 , fee ) ;
else
got_fees = subtract_fees ( & b , & a , & b_fee , & a_fee ,
delta_a < 0 , fee ) ;
if ( ! got_fees )
return false ;
/* Now we know we're succeeding, update caller's state */
a_side - > pay = a ;
b_side - > pay = b ;
a_side - > fee = a_fee ;
b_side - > fee = b_fee ;
return true ;
return true ;
}
}
bool initial_funding ( const OpenChannel * a ,
struct channel_state * initial_funding ( const tal_t * ctx ,
const OpenChannel * b ,
const OpenChannel * a ,
const OpenAnchor * anchor ,
const OpenChannel * b ,
uint64_t fee ,
const OpenAnchor * anchor ,
uint64_t * a_amount ,
uint64_t fee )
uint64_t * b_amount )
{
{
uint64_t channel_delta = 0 ;
struct channel_state * state = talz ( ctx , struct channel_state ) ;
if ( fee > anchor - > amount )
return tal_free ( state ) ;
/* Initially, all goes back to funder. */
state - > a . pay = anchor - > amount - fee ;
state - > a . fee = fee ;
/* If B (not A) is funder, invert. */
if ( is_funder ( b ) )
invert_cstate ( state ) ;
return funding_delta ( a , b , anchor , fee , & channel_delta , 0 ,
/* This checks we only have 1 anchor, and is nice code reuse. */
a_amount , b_amount ) ;
if ( ! funding_delta ( a , b , anchor , 0 , & state - > a , & state - > b ) )
return tal_free ( state ) ;
return state ;
}
}
/* We take the minimum. If one side offers too little, it should be rejected */
/* We take the minimum. If one side offers too little, it should be rejected */
@ -95,3 +118,12 @@ uint64_t commit_fee(const OpenChannel *a, const OpenChannel *b)
return a - > commitment_fee ;
return a - > commitment_fee ;
return b - > commitment_fee ;
return b - > commitment_fee ;
}
}
void invert_cstate ( struct channel_state * cstate )
{
struct channel_oneside tmp ;
tmp = cstate - > a ;
cstate - > a = cstate - > b ;
cstate - > b = tmp ;
}