From d894358bd78dbe316ae81ca20070f46fb85e81f6 Mon Sep 17 00:00:00 2001 From: ueno Date: Wed, 27 Nov 2019 17:51:21 +0900 Subject: [PATCH] fix features endian and update check items --- ln/ln.c | 4 - ln/ln.h | 18 +- ln/ln_anno.c | 52 +-- ln/ln_msg_setupctl.c | 21 +- ln/ln_setupctl.c | 106 ++++-- ln/ln_setupctl.h | 2 +- ln/tests/Makefile | 28 +- ln/tests/test_ln_anno.cpp | 10 +- ln/tests/test_ln_init.cpp | 632 ++++++++++++++++++++++++++++++++ ln/tests/test_ln_proto_init.cpp | 42 +++ ptarmd/conf.c | 8 +- ptarmd/ptarmd.h | 2 +- showdb/showdb.c | 2 +- 13 files changed, 814 insertions(+), 113 deletions(-) create mode 100644 ln/tests/test_ln_init.cpp diff --git a/ln/ln.c b/ln/ln.c index 8a8ecfd80..f07c400a8 100644 --- a/ln/ln.c +++ b/ln/ln.c @@ -233,9 +233,7 @@ bool ln_init( pChannel->commit_info_remote.p_funding_info = &pChannel->funding_info; -#ifdef USE_GOSSIP_QUERY SLIST_INIT(&pChannel->gossip_query.request.send_encoded_ids); -#endif LOGD("END\n"); @@ -1472,7 +1470,6 @@ static void channel_clear(ln_channel_t *pChannel) pChannel->anno_flag = 0; pChannel->shutdown_flag = 0; -#ifdef USE_GOSSIP_QUERY ln_anno_encoded_ids_t *p = SLIST_FIRST(&pChannel->gossip_query.request.send_encoded_ids); while (p) { ln_anno_encoded_ids_t *p_bak = p; @@ -1480,7 +1477,6 @@ static void channel_clear(ln_channel_t *pChannel) utl_buf_free(&p_bak->encoded_short_ids); UTL_DBG_FREE(p_bak); } -#endif ln_establish_free(pChannel); } diff --git a/ln/ln.h b/ln/ln.h index cecb5b409..f8607f974 100644 --- a/ln/ln.h +++ b/ln/ln.h @@ -113,13 +113,23 @@ extern "C" { #define LN_RCLOSE_IDX_TO_REMOTE (1) ///< to_remote #define LN_RCLOSE_IDX_HTLC (2) ///< HTLC +//requires / supports feature #define LN_INIT_LF_OPT_DATALOSS_REQ (1 << 0) ///< option_data_loss_protect #define LN_INIT_LF_OPT_DATALOSS (1 << 1) ///< option_data_loss_protect +#define LN_INIT_LF_ROUTE_SYNC_REQ (1 << 2) ///< [NO]initial_routing_sync #define LN_INIT_LF_ROUTE_SYNC (1 << 3) ///< initial_routing_sync #define LN_INIT_LF_OPT_UPF_SHDN_REQ (1 << 4) ///< option_upfront_shutdown_script #define LN_INIT_LF_OPT_UPF_SHDN (1 << 5) ///< option_upfront_shutdown_script #define LN_INIT_LF_OPT_GSP_QUERY_REQ (1 << 6) ///< gossip_queries #define LN_INIT_LF_OPT_GSP_QUERY (1 << 7) ///< gossip_queries +#define LN_INIT_LF_OPT_VAR_ONION_REQ (1 << 8) ///< var_onion_optin +#define LN_INIT_LF_OPT_VAR_ONION (1 << 9) ///< var_onion_optin +#define LN_INIT_LF_OPT_GQUERY_EX_REQ (1 << 10) ///< gossip_queries_ex +#define LN_INIT_LF_OPT_GQUERY_EX (1 << 11) ///< gossip_queries_ex +#define LN_INIT_LF_OPT_STATIC_RKEY_REQ (1 << 12) ///< option_static_remotekey +#define LN_INIT_LF_OPT_STATIC_RKEY (1 << 13) ///< option_static_remotekey +#define LN_INIT_LF_OPT_15_14_REQ (1 << 14) ///< RFU bit 15/14 + #define LN_INIT_LF_OPT_GSP_QUERIES (LN_INIT_LF_OPT_GSP_QUERY_REQ | LN_INIT_LF_OPT_GSP_QUERY) //XXX: @@ -290,7 +300,6 @@ typedef struct { } ln_anno_param_t; -#ifdef USE_GOSSIP_QUERY /** @struct ln_anno_encoded_ids_t * @brief encided_short_ids list */ @@ -355,7 +364,6 @@ typedef struct { // uint64_t *p_reply_short_ids; ///< decoded short_channel_ids } ln_gossip_query_t; -#endif /// @} @@ -395,8 +403,8 @@ struct ln_channel_t { //msg:establish uint8_t init_flag; ///< [INIT_01]initフラグ(M_INIT_FLAG_xxx) - uint8_t lfeature_local; ///< [INIT_02]initで送信したlocalfeature - uint8_t lfeature_remote; ///< [INIT_03]initで取得したlocalfeature + uint16_t lfeature_local; ///< [INIT_02]initで送信したfeature + uint16_t lfeature_remote; ///< [INIT_03]initで取得したfeature uint64_t reest_next_local_commit_num; ///< [INIT_04]channel_reestablish.next_local_commitment_number uint64_t reest_next_remote_revoke_num; ///< [INIT_05]channel_reestablish.next_remote_revocation_number @@ -427,10 +435,8 @@ struct ln_channel_t { uint8_t prev_remote_commit_txid[BTC_SZ_TXID]; ///< [COMM_03]previous remote commit tx's txid (for second last remote unilateral close) -#ifdef USE_GOSSIP_QUERY //gossip_queries ln_gossip_query_t gossip_query; ///< [GQRY_01]gossip_queries -#endif //last error int err; ///< [ERRO_01]error code(ln_err.h) diff --git a/ln/ln_anno.c b/ln/ln_anno.c index 7bff22eaf..7362a36d8 100644 --- a/ln/ln_anno.c +++ b/ln/ln_anno.c @@ -398,7 +398,6 @@ bool ln_channel_update_disable(ln_channel_t *pChannel) bool ln_query_short_channel_ids_send(ln_channel_t *pChannel, const uint8_t *pEncodedIds, uint16_t Len) { -#ifdef USE_GOSSIP_QUERY if ((pChannel->init_flag & M_INIT_GOSSIP_QUERY) == 0) { LOGE("fail: not gossip_queries\n"); return false; @@ -419,16 +418,11 @@ bool ln_query_short_channel_ids_send(ln_channel_t *pChannel, const uint8_t *pEnc ln_callback(pChannel, LN_CB_TYPE_SEND_MESSAGE, &buf); utl_buf_free(&buf); return true; -#else - (void)pChannel; (void)pEncodedIds; (void)Len; - return false; -#endif } bool HIDDEN ln_query_short_channel_ids_recv(ln_channel_t *pChannel, const uint8_t *pData, uint16_t Len) { -#ifdef USE_GOSSIP_QUERY if ((pChannel->init_flag & M_INIT_GOSSIP_QUERY) == 0) { LOGD("through: not gossip_queries\n"); return true; @@ -442,24 +436,21 @@ bool HIDDEN ln_query_short_channel_ids_recv(ln_channel_t *pChannel, const uint8_ uint64_t *p_short_channel_ids; size_t ids; if (!ln_msg_gossip_ids_decode(&p_short_channel_ids, &ids, msg.p_encoded_short_ids, msg.len)) { + LOGE("fail: ids decode\n"); return false; } if (!ln_db_annoinfos_del_node_id(ln_remote_node_id(pChannel), p_short_channel_ids, ids)) { + LOGE("fail: annoinfo del\n"); return false; } UTL_DBG_FREE(p_short_channel_ids); return true; -#else - (void)pChannel; (void)pData; (void)Len; - return false; -#endif } bool ln_reply_short_channel_ids_end_send(ln_channel_t *pChannel, const ln_msg_query_short_channel_ids_t *pMsg) { -#ifdef USE_GOSSIP_QUERY (void)pMsg; if ((pChannel->init_flag & M_INIT_GOSSIP_QUERY) == 0) { @@ -476,16 +467,11 @@ bool ln_reply_short_channel_ids_end_send(ln_channel_t *pChannel, const ln_msg_qu ln_callback(pChannel, LN_CB_TYPE_SEND_MESSAGE, &buf); utl_buf_free(&buf); return true; -#else - (void)pChannel; (void)pMsg; - return false; -#endif } bool HIDDEN ln_reply_short_channel_ids_end_recv(ln_channel_t *pChannel, const uint8_t *pData, uint16_t Len) { -#ifdef USE_GOSSIP_QUERY if ((pChannel->init_flag & M_INIT_GOSSIP_QUERY) == 0) { LOGE("fail: not gossip_queries\n"); return false; @@ -500,16 +486,11 @@ bool HIDDEN ln_reply_short_channel_ids_end_recv(ln_channel_t *pChannel, const ui } pChannel->gossip_query.request.wait_query_short_channel_ids_end = false; return true; -#else - (void)pChannel; (void)pData; (void)Len; - return false; -#endif } bool ln_query_channel_range_send(ln_channel_t *pChannel, uint32_t FirstBlock, uint32_t Num) { -#ifdef USE_GOSSIP_QUERY if ((pChannel->init_flag & M_INIT_GOSSIP_QUERY) == 0) { LOGE("fail: not gossip_queries\n"); return false; @@ -536,16 +517,11 @@ bool ln_query_channel_range_send(ln_channel_t *pChannel, uint32_t FirstBlock, ui pChannel->gossip_query.request.first_blocknum = FirstBlock; pChannel->gossip_query.request.rest_blocks = Num; return true; -#else - (void)pChannel; (void)FirstBlock; (void)Num; - return false; -#endif } bool HIDDEN ln_query_channel_range_recv(ln_channel_t *pChannel, const uint8_t *pData, uint16_t Len) { -#ifdef USE_GOSSIP_QUERY if ((pChannel->init_flag & M_INIT_GOSSIP_QUERY) == 0) { LOGD("through: not gossip_queries\n"); return true; @@ -559,16 +535,11 @@ bool HIDDEN ln_query_channel_range_recv(ln_channel_t *pChannel, const uint8_t *p return false; } return true; -#else - (void)pChannel; (void)pData; (void)Len; - return false; -#endif } bool ln_reply_channel_range_send(ln_channel_t *pChannel, const ln_msg_query_channel_range_t *pMsg) { -#ifdef USE_GOSSIP_QUERY bool ret; if ((pChannel->init_flag & M_INIT_GOSSIP_QUERY) == 0) { @@ -630,16 +601,11 @@ bool ln_reply_channel_range_send(ln_channel_t *pChannel, const ln_msg_query_chan utl_buf_free(&buf); utl_buf_free(&encoded_ids); return true; -#else - (void)pChannel; (void)pMsg; - return false; -#endif } bool HIDDEN ln_reply_channel_range_recv(ln_channel_t *pChannel, const uint8_t *pData, uint16_t Len) { -#ifdef USE_GOSSIP_QUERY if ((pChannel->init_flag & M_INIT_GOSSIP_QUERY) == 0) { LOGE("fail: not gossip_queries\n"); return false; @@ -737,16 +703,11 @@ bool HIDDEN ln_reply_channel_range_recv(ln_channel_t *pChannel, const uint8_t *p } } return true; -#else - (void)pChannel; (void)pData; (void)Len; - return false; -#endif } bool ln_gossip_timestamp_filter_send(ln_channel_t *pChannel) { -#ifdef USE_GOSSIP_QUERY if ((pChannel->init_flag & M_INIT_GOSSIP_QUERY) == 0) { LOGE("fail: not gossip_queries\n"); return false; @@ -761,16 +722,11 @@ bool ln_gossip_timestamp_filter_send(ln_channel_t *pChannel) ln_callback(pChannel, LN_CB_TYPE_SEND_MESSAGE, &buf); utl_buf_free(&buf); return true; -#else - (void)pChannel; - return false; -#endif } bool HIDDEN ln_gossip_timestamp_filter_recv(ln_channel_t *pChannel, const uint8_t *pData, uint16_t Len) { -#ifdef USE_GOSSIP_QUERY if ((pChannel->init_flag & M_INIT_GOSSIP_QUERY) == 0) { LOGD("through: not gossip_queries\n"); return true; @@ -788,10 +744,6 @@ bool HIDDEN ln_gossip_timestamp_filter_recv(ln_channel_t *pChannel, const uint8_ return true; } return true; -#else - (void)pChannel; (void)pData; (void)Len; - return false; -#endif } diff --git a/ln/ln_msg_setupctl.c b/ln/ln_msg_setupctl.c index 6891452ca..491cec425 100644 --- a/ln/ln_msg_setupctl.c +++ b/ln/ln_msg_setupctl.c @@ -123,12 +123,23 @@ static void init_print(const ln_msg_init_t *pMsg) LOGD("-[init]-------------------------------\n"); LOGD("globalfeatures: "); DUMPD(pMsg->p_globalfeatures, pMsg->gflen); - LOGD("localfeatures: "); + LOGD("features: "); DUMPD(pMsg->p_localfeatures, pMsg->lflen); - LOGD(" option_data_loss_protect: %d\n", (pMsg->p_localfeatures[0] & 0x03)); - LOGD(" initial_routing_sync: %d\n", (pMsg->p_localfeatures[0] & 0x0c) >> 2); - LOGD(" option_upfront_shutdown_script: %d\n", (pMsg->p_localfeatures[0] & 0x30) >> 4); - LOGD(" gossip_queries: %d\n", (pMsg->p_localfeatures[0] & 0xc0) >> 6); + //b7-0 + if (pMsg->lflen > 0) { + const uint8_t feature = pMsg->p_localfeatures[pMsg->lflen - 1]; + LOGD(" option_data_loss_protect: %d\n", (feature & 0x03)); + LOGD(" initial_routing_sync: %d\n", (feature & 0x0c) >> 2); + LOGD(" option_upfront_shutdown_script: %d\n", (feature & 0x30) >> 4); + LOGD(" gossip_queries: %d\n", (feature & 0xc0) >> 6); + } + //b15-8 + if (pMsg->lflen > 1) { + const uint8_t feature = pMsg->p_localfeatures[pMsg->lflen - 2]; + LOGD(" var_onion_optin: %d\n", (feature & 0x03)); + LOGD(" gossip_queries_ex: %d\n", (feature & 0x0c) >> 2); + LOGD(" option_static_remotekey: %d\n", (feature & 0x30) >> 4); + } LOGD("--------------------------------\n"); #else (void)pMsg; diff --git a/ln/ln_setupctl.c b/ln/ln_setupctl.c index 1a16ac3bf..b50865370 100644 --- a/ln/ln_setupctl.c +++ b/ln/ln_setupctl.c @@ -52,7 +52,7 @@ **************************************************************************/ /// init.localfeatures default value -static uint8_t mInitLocalFeatures[1]; +static uint16_t mInitLocalFeatures; /************************************************************************** @@ -63,10 +63,10 @@ static uint8_t mInitLocalFeatures[1]; * public functions **************************************************************************/ -void ln_init_localfeatures_set(uint8_t lf) +void ln_init_localfeatures_set(uint16_t lf) { - LOGD("localfeatures=0x%02x\n", lf); - mInitLocalFeatures[0] = lf; + LOGD("localfeatures=0x%04x\n", lf); + mInitLocalFeatures = lf; } @@ -94,12 +94,21 @@ bool /*HIDDEN*/ ln_init_send(ln_channel_t *pChannel, bool bInitRouteSync, bool b ln_msg_init_t msg; msg.gflen = 0; msg.p_globalfeatures = NULL; - pChannel->lfeature_local = mInitLocalFeatures[0] | (bInitRouteSync ? LN_INIT_LF_ROUTE_SYNC : 0); -#ifdef USE_GOSSIP_QUERY - pChannel->lfeature_local |= LN_INIT_LF_OPT_GSP_QUERY; -#endif //USE_GOSSIP_QUERY + pChannel->lfeature_local = mInitLocalFeatures | (bInitRouteSync ? LN_INIT_LF_ROUTE_SYNC : 0); msg.lflen = sizeof(pChannel->lfeature_local); - msg.p_localfeatures = &pChannel->lfeature_local; + uint8_t lfeature[sizeof(uint16_t)]; + utl_int_unpack_u16be(lfeature, pChannel->lfeature_local); + + //shorten + const uint8_t *p_lfeature = lfeature; + for (size_t lp = 0; lp < sizeof(lfeature); lp++) { + if (*p_lfeature == 0) { + p_lfeature++; + msg.lflen--; + } + } + msg.p_localfeatures = p_lfeature; + LOGD("localfeatures: "); DUMPD(msg.p_localfeatures, msg.lflen); utl_buf_t buf = UTL_BUF_INIT; @@ -119,6 +128,7 @@ bool /*HIDDEN*/ ln_init_send(ln_channel_t *pChannel, bool bInitRouteSync, bool b bool HIDDEN ln_init_recv(ln_channel_t *pChannel, const uint8_t *pData, uint16_t Len) { bool ret = false; + uint16_t feature = 0; if (pChannel->init_flag & M_INIT_FLAG_RECV) { //TODO: multiple init error @@ -133,6 +143,13 @@ bool HIDDEN ln_init_recv(ln_channel_t *pChannel, const uint8_t *pData, uint16_t } //globalfeatures not assigned + if ( (msg.gflen > 2) || + ((msg.gflen == 2) && ((msg.p_globalfeatures[0] & 0xc0) != 0)) ) { + // BOLT1: + // - SHOULD NOT set features greater than 13 in globalfeatures. + LOGE("fail: globalfeature greater than 13.\n"); + goto LABEL_EXIT; + } for (uint32_t lp = 0; lp < msg.gflen; lp++) { if (msg.p_globalfeatures[lp] & 0x55) { //even bits LOGE("fail: unknown bit(globalfeatures)\n"); @@ -140,28 +157,65 @@ bool HIDDEN ln_init_recv(ln_channel_t *pChannel, const uint8_t *pData, uint16_t } } - pChannel->lfeature_remote = 0x00; - if (msg.lflen) { - //2018/06/27(commit: f6312d9a702ede0f85e094d75fd95c5e3b245bcf) - // https://github.com/lightningnetwork/lightning-rfc/blob/f6312d9a702ede0f85e094d75fd95c5e3b245bcf/09-features.md#assigned-localfeatures-flags - // bit0 : option_data_loss_protect - // bit2 : (none) - // bit4 : option_upfront_shutdown_script - // bit6 : gossip_queries - if (msg.p_localfeatures[0] & (LN_INIT_LF_OPT_UPF_SHDN_REQ | LN_INIT_LF_OPT_GSP_QUERY_REQ)) { //even bits - LOGE("fail: unknown bit(localfeatures)\n"); - goto LABEL_EXIT; - } - - for (uint32_t lp = 1; lp < msg.lflen; lp++) { - if (msg.p_localfeatures[lp] & 0x55) { //even bits - LOGE("fail: unknown bit(localfeatures)\n"); + //2019/11/27(commit: 8e69306e0a93375a1bbb1a0099f7ce3025ae4c0f) + // https://github.com/lightningnetwork/lightning-rfc/commit/8e69306e0a93375a1bbb1a0099f7ce3025ae4c0f + // bit 1/ 0 : option_data_loss_protect + // bit 3/ - : initial_routing_sync + // bit 5/ 4 : option_upfront_shutdown_script + // bit 7/ 6 : gossip_queries + // bit 9/ 8 : var_onion_optin + // bit11/10 : gossip_queries_ex + // bit13/12 : option_static_remotekey + if (msg.lflen > 0) { + feature = msg.p_localfeatures[msg.lflen - 1]; + } + if (msg.lflen > 1) { + feature |= msg.p_localfeatures[msg.lflen - 2] << 8; + } + if (msg.lflen > 2) { + for (int lp = 0; lp < msg.lflen - 2; lp++) { + if (msg.p_localfeatures[msg.lflen - lp] && 0x55) { + LOGE("fail: Ptarmigan not support\n"); goto LABEL_EXIT; } } - pChannel->lfeature_remote = msg.p_localfeatures[0]; } + //require feature + if (feature & LN_INIT_LF_ROUTE_SYNC_REQ) { + LOGE("fail: invalid feature bit 2\n"); + goto LABEL_EXIT; + } + if (feature & LN_INIT_LF_OPT_UPF_SHDN_REQ) { + LOGE("fail: Ptarmigan not support: option_upfront_shutdown_script\n"); + goto LABEL_EXIT; + } + if (feature & LN_INIT_LF_OPT_GSP_QUERY_REQ) { +#ifdef USE_GOSSIP_QUERY + LOGD("support: gossip_queries\n"); +#else + LOGE("fail: Ptarmigan not support: gossip_queries\n"); + goto LABEL_EXIT; +#endif + } + if (feature & LN_INIT_LF_OPT_VAR_ONION_REQ) { + LOGE("fail: Ptarmigan not support: var_onion_optin\n"); + goto LABEL_EXIT; + } + if (feature & LN_INIT_LF_OPT_GQUERY_EX_REQ) { + LOGE("fail: Ptarmigan not support: gossip_queries_ex\n"); + goto LABEL_EXIT; + } + if (feature & LN_INIT_LF_OPT_STATIC_RKEY_REQ) { + LOGE("fail: Ptarmigan not support: option_static_remotekey\n"); + goto LABEL_EXIT; + } + if (feature & LN_INIT_LF_OPT_15_14_REQ) { + LOGE("fail: invalid feature bit 15/14\n"); + goto LABEL_EXIT; + } + pChannel->lfeature_remote = feature; + //gossip_queries if ( (pChannel->lfeature_local & LN_INIT_LF_OPT_GSP_QUERIES) && (pChannel->lfeature_remote & LN_INIT_LF_OPT_GSP_QUERIES) ) { diff --git a/ln/ln_setupctl.h b/ln/ln_setupctl.h index bd0366916..333b80f19 100644 --- a/ln/ln_setupctl.h +++ b/ln/ln_setupctl.h @@ -72,7 +72,7 @@ * 未設定の場合はデフォルト値が使用される。 * */ -void ln_init_localfeatures_set(uint8_t lf); +void ln_init_localfeatures_set(uint16_t lf); void /*HIDDEN*/ ln_error_set(ln_channel_t *pChannel, int Err, const char *pFormat, ...); diff --git a/ln/tests/Makefile b/ln/tests/Makefile index 353a72181..4095dade9 100644 --- a/ln/tests/Makefile +++ b/ln/tests/Makefile @@ -6,29 +6,25 @@ MK := mkdir RM := rm -rf TEST_TARGET_SRC += \ - test_ln_proto_updatechannel.cpp \ - test_ln_msg_close.cpp \ - test_ln_msg_normalope.cpp \ - test_ln_msg_anno.cpp \ + test_ln_anno.cpp \ + test_ln_bech32.cpp \ test_ln_bolt.cpp \ test_ln_htlcflag.cpp \ - test_ln.cpp \ + test_ln_msg_anno_gossip_zlib.cpp \ + test_ln_msg_anno_gossip.cpp \ + test_ln_msg_anno.cpp \ + test_ln_msg_close.cpp \ + test_ln_msg_normalope.cpp \ test_ln_node.cpp \ + test_ln_proto_acceptchannel.cpp \ test_ln_proto_init.cpp \ test_ln_proto_openchannel.cpp \ - test_ln_proto_acceptchannel.cpp \ test_ln_proto_updateaddhtlc.cpp \ + test_ln_proto_updatechannel.cpp \ test_ln_proto_updatefee.cpp \ - test_ln_bech32.cpp \ - test_ln_tlv.cpp - -# TEST_TARGET_SRC += \ -# test_ln_msg_anno_gossip.cpp \ -# test_ln_anno.cpp - -# #remove -lz -# TEST_TARGET_SRC += \ -# test_ln_msg_anno_gossip_zlib.cpp + test_ln_tlv.cpp \ + test_ln_init.cpp \ + test_ln.cpp include ../../options.mak diff --git a/ln/tests/test_ln_anno.cpp b/ln/tests/test_ln_anno.cpp index 1442f2682..810882b82 100644 --- a/ln/tests/test_ln_anno.cpp +++ b/ln/tests/test_ln_anno.cpp @@ -30,6 +30,7 @@ extern "C" { // #include "../../btc/btc_test_util.c" #undef LOG_TAG +#include "ln_setupctl.h" #include "ln_anno.c" #include "ln.c" } @@ -52,6 +53,13 @@ FAKE_VALUE_FUNC(bool, ln_msg_gossip_timestamp_filter_read, ln_msg_gossip_timesta FAKE_VALUE_FUNC(bool, ln_msg_gossip_ids_encode, utl_buf_t *, const uint64_t *, size_t ); FAKE_VALUE_FUNC(bool, ln_msg_gossip_ids_decode, uint64_t **, size_t *, const uint8_t *, size_t ); +FAKE_VALUE_FUNC(bool, ln_db_annoinfos_del_node_id, const uint8_t *, const uint64_t *, size_t); +FAKE_VALUE_FUNC(bool, ln_db_anno_transaction) +FAKE_VOID_FUNC(ln_db_anno_commit, bool) +FAKE_VALUE_FUNC(bool, ln_db_anno_cur_open, void **, ln_db_cur_t); +FAKE_VOID_FUNC(ln_db_anno_cur_close, void *); +FAKE_VALUE_FUNC(bool, ln_db_cnlanno_cur_get, void*, uint64_t*, char *, uint32_t *, utl_buf_t *); +FAKE_VALUE_FUNC(bool, ln_db_annoinfos_del_timestamp, const uint8_t *, uint32_t , uint32_t ); //////////////////////////////////////////////////////////////////////// @@ -65,7 +73,7 @@ namespace LN_DUMMY { class ln: public testing::Test { protected: virtual void SetUp() { - //utl_log_init_stderr(); + utl_log_init_stderr(); RESET_FAKE(ln_msg_query_short_channel_ids_write) RESET_FAKE(ln_msg_reply_short_channel_ids_end_write) RESET_FAKE(ln_msg_query_channel_range_write) diff --git a/ln/tests/test_ln_init.cpp b/ln/tests/test_ln_init.cpp new file mode 100644 index 000000000..9be1f6269 --- /dev/null +++ b/ln/tests/test_ln_init.cpp @@ -0,0 +1,632 @@ +#include "gtest/gtest.h" +#include +#include "tests/fff.h" +DEFINE_FFF_GLOBALS; + + +extern "C" { +#undef LOG_TAG +#include "../../utl/utl_thread.c" +#undef LOG_TAG +#include "../../utl/utl_log.c" +#include "../../utl/utl_dbg.c" +#include "../../utl/utl_buf.c" +#include "../../utl/utl_push.c" +#include "../../utl/utl_time.c" +#include "../../utl/utl_int.c" +#include "../../utl/utl_str.c" +#include "../../utl/utl_mem.c" +#undef LOG_TAG +#include "../../btc/btc.c" +#include "../../btc/btc_buf.c" +#include "../../btc/btc_extkey.c" +#include "../../btc/btc_keys.c" +#include "../../btc/btc_sw.c" +#include "../../btc/btc_sig.c" +#include "../../btc/btc_script.c" +#include "../../btc/btc_tx.c" +#include "../../btc/btc_tx_buf.c" +#include "../../btc/btc_crypto.c" +#include "../../btc/segwit_addr.c" +#include "../../btc/btc_segwit_addr.c" +#include "../../btc/btc_test_util.c" + +#undef LOG_TAG +#include "ln_derkey.c" +#include "ln_derkey_ex.c" +#include "ln_msg_anno.c" +#include "ln_msg_close.c" +//#include "ln_msg_establish.c" +#include "ln_msg_normalope.c" +#include "ln_node.c" +#include "ln_onion.c" +#include "ln_script.c" +#include "ln_noise.c" +#include "ln_signer.c" +#include "ln_invoice.c" +#include "ln_print.c" +#include "ln_update.c" +#include "ln_update_info.c" + +#include "ln.c" +#include "ln_setupctl.c" +} + +//////////////////////////////////////////////////////////////////////// +//FAKE関数 + +// FAKE_VOID_FUNC(ln_db_preimage_cur_close, void *); +// FAKE_VALUE_FUNC(bool, ln_db_cnlupd_load, utl_buf_t *, uint32_t *, uint64_t, uint8_t); +// FAKE_VALUE_FUNC(bool, ln_db_preimage_del, const uint8_t *); +// FAKE_VALUE_FUNC(bool, ln_db_preimage_cur_open, void **); +// FAKE_VALUE_FUNC(bool, ln_db_preimage_cur_get, void *, bool *, ln_db_preimage_t *, const char**); +// FAKE_VALUE_FUNC(bool, ln_db_channel_search, ln_db_func_cmp_t, void *); +// FAKE_VALUE_FUNC(bool, ln_db_channel_search_readonly, ln_db_func_cmp_t, void *); +// FAKE_VALUE_FUNC(bool, ln_db_payment_hash_save, const uint8_t*, const uint8_t*, ln_commit_tx_output_type_t, uint32_t); +// FAKE_VALUE_FUNC(bool, ln_db_preimage_search, ln_db_func_preimage_t, void*); + +// FAKE_VALUE_FUNC(bool, ln_msg_open_channel_write, utl_buf_t *, const ln_open_channel_t *); +// FAKE_VALUE_FUNC(bool, ln_msg_open_channel_read, ln_open_channel_t*, const uint8_t*, uint16_t); +// FAKE_VALUE_FUNC(bool, ln_msg_accept_channel_write, utl_buf_t *, const ln_msg_accept_channel_t *); +// FAKE_VALUE_FUNC(bool, ln_msg_accept_channel_read, ln_msg_accept_channel_t *, const uint8_t *, uint16_t ); +// FAKE_VALUE_FUNC(bool, ln_msg_funding_created_write, utl_buf_t *, const ln_funding_writed_t *); +// FAKE_VALUE_FUNC(bool, ln_msg_funding_created_read, ln_msg_funding_created_t *, const uint8_t *, uint16_t ); +// FAKE_VALUE_FUNC(bool, ln_msg_funding_signed_write, utl_buf_t *, const ln_msg_funding_signed_t *); +// FAKE_VALUE_FUNC(bool, ln_msg_funding_signed_read, ln_msg_funding_signed_t *, const uint8_t *, uint16_t ); + +FAKE_VALUE_FUNC(bool, ln_msg_init_write, utl_buf_t *, const ln_msg_init_t *); +FAKE_VALUE_FUNC(bool, ln_msg_init_read, ln_msg_init_t *, const uint8_t *, uint16_t ); + +FAKE_VALUE_FUNC(bool, ln_db_channel_save, const ln_channel_t *); + +FAKE_VALUE_FUNC(bool, ln_msg_error_write, utl_buf_t *, const ln_msg_error_t *); + + +//////////////////////////////////////////////////////////////////////// + +class ln: public testing::Test { +protected: + virtual void SetUp() { + //utl_log_init_stderr(); + RESET_FAKE(ln_msg_init_write) + RESET_FAKE(ln_msg_init_read) + + ln_db_channel_save_fake.return_val = true; + ln_msg_error_write_fake.return_val = true; + + utl_dbg_malloc_cnt_reset(); + btc_init(BTC_BLOCK_CHAIN_BTCTEST, true); + } + + virtual void TearDown() { + ln_node_term(); + btc_term(); + ASSERT_EQ(0, utl_dbg_malloc_cnt()); + } + +public: + static void DumpBin(const uint8_t *pData, uint16_t Len) + { + for (uint16_t lp = 0; lp < Len; lp++) { + printf("%02x", pData[lp]); + } + printf("\n"); + } + static bool DumpCheck(const void *pData, uint32_t Len, uint8_t Fill) + { + bool ret = true; + const uint8_t *p = (const uint8_t *)pData; + for (uint32_t lp = 0; lp < Len; lp++) { + if (p[lp] != Fill) { + ret = false; + break; + } + } + return ret; + } + static void LnCallbackType(ln_cb_type_t Type, void *pCommonParam, void *pTypeSpecificParam) { + (void)pCommonParam; (void)pTypeSpecificParam; + const char *p_str; + switch (Type) { + case LN_CB_TYPE_STOP_CHANNEL: p_str = "LN_CB_TYPE_STOP_CHANNEL"; break; + case LN_CB_TYPE_NOTIFY_ERROR: p_str = "LN_CB_TYPE_NOTIFY_ERROR"; break; + case LN_CB_TYPE_SEND_ERROR: p_str = "LN_CB_TYPE_SEND_ERROR"; break; + case LN_CB_TYPE_NOTIFY_INIT_RECV: p_str = "LN_CB_TYPE_NOTIFY_INIT_RECV"; break; + case LN_CB_TYPE_NOTIFY_REESTABLISH_RECV: p_str = "LN_CB_TYPE_NOTIFY_REESTABLISH_RECV"; break; + case LN_CB_TYPE_SIGN_FUNDING_TX: p_str = "LN_CB_TYPE_SIGN_FUNDING_TX"; break; + case LN_CB_TYPE_WAIT_FUNDING_TX: p_str = "LN_CB_TYPE_WAIT_FUNDING_TX"; break; + case LN_CB_TYPE_NOTIFY_FUNDING_LOCKED_RECV: p_str = "LN_CB_TYPE_NOTIFY_FUNDING_LOCKED_RECV"; break; + case LN_CB_TYPE_NOTIFY_ANNODB_UPDATE: p_str = "LN_CB_TYPE_NOTIFY_ANNODB_UPDATE"; break; + case LN_CB_TYPE_NOTIFY_ADDFINAL_HTLC_RECV: p_str = "LN_CB_TYPE_NOTIFY_ADDFINAL_HTLC_RECV"; break; + case LN_CB_TYPE_START_BWD_DEL_HTLC: p_str = "LN_CB_TYPE_START_BWD_DEL_HTLC"; break; + case LN_CB_TYPE_NOTIFY_FULFILL_HTLC_RECV: p_str = "LN_CB_TYPE_NOTIFY_FULFILL_HTLC_RECV"; break; + case LN_CB_TYPE_NOTIFY_REV_AND_ACK_EXCHANGE: p_str = "LN_CB_TYPE_NOTIFY_REV_AND_ACK_EXCHANGE"; break; + case LN_CB_TYPE_NOTIFY_UPDATE_FEE_RECV: p_str = "LN_CB_TYPE_NOTIFY_UPDATE_FEE_RECV"; break; + case LN_CB_TYPE_NOTIFY_SHUTDOWN_RECV: p_str = "LN_CB_TYPE_NOTIFY_SHUTDOWN_RECV"; break; + case LN_CB_TYPE_UPDATE_CLOSING_FEE: p_str = "LN_CB_TYPE_UPDATE_CLOSING_FEE"; break; + case LN_CB_TYPE_NOTIFY_CLOSING_END: p_str = "LN_CB_TYPE_NOTIFY_CLOSING_END"; break; + case LN_CB_TYPE_SEND_MESSAGE: p_str = "LN_CB_TYPE_SEND_MESSAGE"; break; + case LN_CB_TYPE_GET_LATEST_FEERATE: p_str = "LN_CB_TYPE_GET_LATEST_FEERATE"; break; + case LN_CB_TYPE_GET_BLOCK_COUNT: p_str = "LN_CB_TYPE_GET_BLOCK_COUNT"; break; + case LN_CB_TYPE_NOTIFY_PONG_RECV: p_str = "LN_CB_TYPE_NOTIFY_PONG_RECV"; break; + default: + p_str = "unknown"; + } + printf("*** callback: %s(%d)\n", p_str, Type); + } + static void LnInit(ln_channel_t *pChannel) + { + ln_anno_param_t anno_param; + + memset(pChannel, 0xcc, sizeof(ln_channel_t)); + anno_param.cltv_expiry_delta = 10; + anno_param.htlc_minimum_msat = 1000; + anno_param.fee_base_msat = 20; + anno_param.fee_prop_millionths = 200; + ln_init(pChannel, &anno_param, NULL, (ln_callback_t)0x123456, NULL); + pChannel->commit_info_local.dust_limit_sat = BTC_DUST_LIMIT; + pChannel->commit_info_local.htlc_minimum_msat = 0; + pChannel->commit_info_local.max_accepted_htlcs = 10; + pChannel->commit_info_local.local_msat = 1000000; + pChannel->commit_info_local.remote_msat = 1000000; + pChannel->commit_info_remote.dust_limit_sat = BTC_DUST_LIMIT; + pChannel->commit_info_remote.htlc_minimum_msat = 0; + pChannel->commit_info_remote.max_accepted_htlcs = 10; + pChannel->commit_info_remote.local_msat = 1000000; + pChannel->commit_info_remote.remote_msat = 1000000; + btc_tx_init(&pChannel->funding_info.tx_data); + utl_buf_init(&pChannel->funding_info.wit_script); + pChannel->p_callback = LnCallbackType; + } +}; + + +//////////////////////////////////////////////////////////////////////// + +TEST_F(ln, ln_init_send1) +{ + ln_channel_t channel; + LnInit(&channel); + + channel.init_flag = M_INIT_FLAG_SEND; + bool init_route_sync = false; + bool have_channel = false; + ASSERT_FALSE(ln_init_send(&channel, init_route_sync, have_channel)); +} + +TEST_F(ln, ln_init_send_none_feature) +{ + ln_channel_t channel; + LnInit(&channel); + + class dummy { + public: + static bool ln_msg_init_write(utl_buf_t *pBuf, const ln_msg_init_t *pMsg) { + EXPECT_EQ(0, pMsg->gflen); + EXPECT_EQ(0, pMsg->lflen); + return true; + } + }; + ln_msg_init_write_fake.custom_fake = dummy::ln_msg_init_write; + + mInitLocalFeatures = 0; + bool init_route_sync = false; + bool have_channel = false; + ASSERT_TRUE(ln_init_send(&channel, init_route_sync, have_channel)); +} + +TEST_F(ln, ln_init_send_one_feature) +{ + ln_channel_t channel; + LnInit(&channel); + + class dummy { + public: + static bool ln_msg_init_write(utl_buf_t *pBuf, const ln_msg_init_t *pMsg) { + EXPECT_EQ(0, pMsg->gflen); + EXPECT_EQ(1, pMsg->lflen); + EXPECT_EQ(0x55, pMsg->p_localfeatures[0]); + return true; + } + }; + ln_msg_init_write_fake.custom_fake = dummy::ln_msg_init_write; + + mInitLocalFeatures = 0x55; + bool init_route_sync = false; + bool have_channel = false; + ASSERT_TRUE(ln_init_send(&channel, init_route_sync, have_channel)); +} + +TEST_F(ln, ln_init_send_two_feature) +{ + ln_channel_t channel; + LnInit(&channel); + + class dummy { + public: + static bool ln_msg_init_write(utl_buf_t *pBuf, const ln_msg_init_t *pMsg) { + EXPECT_EQ(0, pMsg->gflen); + EXPECT_EQ(2, pMsg->lflen); + EXPECT_EQ(0xaa, pMsg->p_localfeatures[0]); + EXPECT_EQ(0x55, pMsg->p_localfeatures[1]); + return true; + } + }; + ln_msg_init_write_fake.custom_fake = dummy::ln_msg_init_write; + + mInitLocalFeatures = 0xaa55; + bool init_route_sync = false; + bool have_channel = false; + ASSERT_TRUE(ln_init_send(&channel, init_route_sync, have_channel)); +} + + +//////////////////////////////////////////////////////////////////////// + +TEST_F(ln, ln_init_recv1) +{ + ln_channel_t channel; + LnInit(&channel); + + channel.init_flag = M_INIT_FLAG_RECV; + ASSERT_FALSE(ln_init_recv(&channel, NULL, 0)); +} + + +TEST_F(ln, ln_init_recv_no_feature) +{ + ln_channel_t channel; + LnInit(&channel); + + class dummy { + public: + static bool ln_msg_init_read(ln_msg_init_t *pMsg, const uint8_t *pData, uint16_t Len) { + (void)pData; (void)Len; + pMsg->gflen = 0; + pMsg->p_globalfeatures = NULL; + pMsg->lflen = 0; + pMsg->p_localfeatures = NULL; + return true; + } + }; + ln_msg_init_read_fake.custom_fake = dummy::ln_msg_init_read; + + ASSERT_TRUE(ln_init_recv(&channel, NULL, 0)); + ASSERT_EQ(0, channel.lfeature_remote); + ASSERT_NE(0, channel.init_flag & M_INIT_FLAG_RECV); + ASSERT_EQ(0, channel.init_flag & M_INIT_GOSSIP_QUERY); +} + + +TEST_F(ln, ln_init_recv_even_gfeature) +{ + ln_channel_t channel; + LnInit(&channel); + + static const uint8_t GFEATURE[] = { 0x55 }; + class dummy { + public: + static bool ln_msg_init_read(ln_msg_init_t *pMsg, const uint8_t *pData, uint16_t Len) { + (void)pData; (void)Len; + pMsg->gflen = sizeof(GFEATURE); + pMsg->p_globalfeatures = GFEATURE; + pMsg->lflen = 0; + pMsg->p_localfeatures = NULL; + return true; + } + }; + ln_msg_init_read_fake.custom_fake = dummy::ln_msg_init_read; + + ASSERT_FALSE(ln_init_recv(&channel, NULL, 0)); + ASSERT_EQ(0, channel.lfeature_remote); + ASSERT_EQ(0, channel.init_flag & M_INIT_FLAG_RECV); + ASSERT_EQ(0, channel.init_flag & M_INIT_GOSSIP_QUERY); +} + + +TEST_F(ln, ln_init_recv_odd_gfeature) +{ + ln_channel_t channel; + LnInit(&channel); + + static const uint8_t GFEATURE[] = { 0xaa }; + class dummy { + public: + static bool ln_msg_init_read(ln_msg_init_t *pMsg, const uint8_t *pData, uint16_t Len) { + (void)pData; (void)Len; + pMsg->gflen = sizeof(GFEATURE); + pMsg->p_globalfeatures = GFEATURE; + pMsg->lflen = 0; + pMsg->p_localfeatures = NULL; + return true; + } + }; + ln_msg_init_read_fake.custom_fake = dummy::ln_msg_init_read; + + ASSERT_TRUE(ln_init_recv(&channel, NULL, 0)); + ASSERT_EQ(0, channel.lfeature_remote); + ASSERT_NE(0, channel.init_flag & M_INIT_FLAG_RECV); + ASSERT_EQ(0, channel.init_flag & M_INIT_GOSSIP_QUERY); +} + + +TEST_F(ln, ln_init_recv_greater_gfeature1) +{ + ln_channel_t channel; + LnInit(&channel); + + static const uint8_t GFEATURE[] = { 0x40, 0x00 }; //bit 13 + class dummy { + public: + static bool ln_msg_init_read(ln_msg_init_t *pMsg, const uint8_t *pData, uint16_t Len) { + (void)pData; (void)Len; + pMsg->gflen = sizeof(GFEATURE); + pMsg->p_globalfeatures = GFEATURE; + pMsg->lflen = 0; + pMsg->p_localfeatures = NULL; + return true; + } + }; + ln_msg_init_read_fake.custom_fake = dummy::ln_msg_init_read; + + ASSERT_FALSE(ln_init_recv(&channel, NULL, 0)); +} + + +TEST_F(ln, ln_init_recv_greater_gfeature2) +{ + ln_channel_t channel; + LnInit(&channel); + + static const uint8_t GFEATURE[] = { 0x80, 0x00 }; //bit 14 + class dummy { + public: + static bool ln_msg_init_read(ln_msg_init_t *pMsg, const uint8_t *pData, uint16_t Len) { + (void)pData; (void)Len; + pMsg->gflen = sizeof(GFEATURE); + pMsg->p_globalfeatures = GFEATURE; + pMsg->lflen = 0; + pMsg->p_localfeatures = NULL; + return true; + } + }; + ln_msg_init_read_fake.custom_fake = dummy::ln_msg_init_read; + + ASSERT_FALSE(ln_init_recv(&channel, NULL, 0)); +} + + +TEST_F(ln, ln_init_recv_greater_gfeature3) +{ + ln_channel_t channel; + LnInit(&channel); + + //通常は先頭が0x00ということは無いし、greater than 13なのでエラーにする + static const uint8_t GFEATURE[] = { 0x00, 0x20, 0x00 }; //3bytes + class dummy { + public: + static bool ln_msg_init_read(ln_msg_init_t *pMsg, const uint8_t *pData, uint16_t Len) { + (void)pData; (void)Len; + pMsg->gflen = sizeof(GFEATURE); + pMsg->p_globalfeatures = GFEATURE; + pMsg->lflen = 0; + pMsg->p_localfeatures = NULL; + return true; + } + }; + ln_msg_init_read_fake.custom_fake = dummy::ln_msg_init_read; + + ASSERT_FALSE(ln_init_recv(&channel, NULL, 0)); +} + + +TEST_F(ln, ln_init_recv_even_lfeature1) +{ + ln_channel_t channel; + LnInit(&channel); + + static const uint8_t LFEATURE[] = { 0x55 }; + class dummy { + public: + static bool ln_msg_init_read(ln_msg_init_t *pMsg, const uint8_t *pData, uint16_t Len) { + (void)pData; (void)Len; + pMsg->gflen = sizeof(LFEATURE); + pMsg->p_globalfeatures = LFEATURE; + pMsg->lflen = 0; + pMsg->p_localfeatures = NULL; + return true; + } + }; + ln_msg_init_read_fake.custom_fake = dummy::ln_msg_init_read; + + ASSERT_FALSE(ln_init_recv(&channel, NULL, 0)); + ASSERT_EQ(0, channel.lfeature_remote); + ASSERT_EQ(0, channel.init_flag & M_INIT_FLAG_RECV); + ASSERT_EQ(0, channel.init_flag & M_INIT_GOSSIP_QUERY); +} + + +TEST_F(ln, ln_init_recv_odd_lfeature1) +{ + ln_channel_t channel; + LnInit(&channel); + + static const uint8_t LFEATURE[] = { 0xaa }; + class dummy { + public: + static bool ln_msg_init_read(ln_msg_init_t *pMsg, const uint8_t *pData, uint16_t Len) { + (void)pData; (void)Len; + pMsg->gflen = 0; + pMsg->p_globalfeatures = NULL; + pMsg->lflen = sizeof(LFEATURE); + pMsg->p_localfeatures = LFEATURE; + return true; + } + }; + ln_msg_init_read_fake.custom_fake = dummy::ln_msg_init_read; + + ASSERT_TRUE(ln_init_recv(&channel, NULL, 0)); + ASSERT_EQ(0xaa, channel.lfeature_remote); + ASSERT_NE(0, channel.init_flag & M_INIT_FLAG_RECV); + ASSERT_EQ(0, channel.init_flag & M_INIT_GOSSIP_QUERY); +} + + +TEST_F(ln, ln_init_recv_even_lfeature2) +{ + ln_channel_t channel; + LnInit(&channel); + + static const uint8_t LFEATURE[] = { 0x55, 0x55 }; + class dummy { + public: + static bool ln_msg_init_read(ln_msg_init_t *pMsg, const uint8_t *pData, uint16_t Len) { + (void)pData; (void)Len; + pMsg->gflen = 0; + pMsg->p_globalfeatures = NULL; + pMsg->lflen = sizeof(LFEATURE); + pMsg->p_localfeatures = LFEATURE; + return true; + } + }; + ln_msg_init_read_fake.custom_fake = dummy::ln_msg_init_read; + + ASSERT_FALSE(ln_init_recv(&channel, NULL, 0)); + ASSERT_EQ(0, channel.lfeature_remote); + ASSERT_EQ(0, channel.init_flag & M_INIT_FLAG_RECV); + ASSERT_EQ(0, channel.init_flag & M_INIT_GOSSIP_QUERY); +} + + +TEST_F(ln, ln_init_recv_odd_lfeature2) +{ + ln_channel_t channel; + LnInit(&channel); + + static const uint8_t LFEATURE[] = { 0xaa, 0xaa }; + class dummy { + public: + static bool ln_msg_init_read(ln_msg_init_t *pMsg, const uint8_t *pData, uint16_t Len) { + (void)pData; (void)Len; + pMsg->gflen = 0; + pMsg->p_globalfeatures = NULL; + pMsg->lflen = sizeof(LFEATURE); + pMsg->p_localfeatures = LFEATURE; + return true; + } + }; + ln_msg_init_read_fake.custom_fake = dummy::ln_msg_init_read; + + ASSERT_TRUE(ln_init_recv(&channel, NULL, 0)); + ASSERT_EQ(0xaaaa, channel.lfeature_remote); + ASSERT_NE(0, channel.init_flag & M_INIT_FLAG_RECV); + ASSERT_EQ(0, channel.init_flag & M_INIT_GOSSIP_QUERY); +} + + +TEST_F(ln, ln_init_recv_even_lfeature_req_no) +{ + ln_channel_t channel; + LnInit(&channel); + + static const uint8_t LFEATURE[][2] = { + //{ 0x00, 0x01 }, //option_data_loss_protect + { 0x00, 0x04 }, //initial_routing_sync(no REQUIRE feature) + { 0x00, 0x10 }, //option_upfront_shutdown_script +#ifndef USE_GOSSIP_QUERY + { 0x00, 0x40 }, //gossip_queries +#endif + { 0x01, 0x00 }, //var_onion_optin + { 0x04, 0x00 }, //gossip_queries_ex + { 0x10, 0x00 }, //option_static_remotekey + { 0x40, 0x00 }, //RFU + }; + static const uint8_t *pLFeature; + class dummy { + public: + static bool ln_msg_init_read(ln_msg_init_t *pMsg, const uint8_t *pData, uint16_t Len) { + (void)pData; (void)Len; + pMsg->gflen = 0; + pMsg->p_globalfeatures = NULL; + pMsg->lflen = 2; + pMsg->p_localfeatures = pLFeature; + return true; + } + }; + ln_msg_init_read_fake.custom_fake = dummy::ln_msg_init_read; + + for (size_t lp = 0; lp < ARRAY_SIZE(LFEATURE); lp++) { + pLFeature = LFEATURE[lp]; + channel.init_flag = 0; + channel.lfeature_remote = 0; + //printf("[%d]%02x %02x\n", (int)lp, pLFeature[0], pLFeature[1]); + ASSERT_FALSE(ln_init_recv(&channel, NULL, 0)); + ASSERT_EQ(0, channel.lfeature_remote); + } +} + +TEST_F(ln, ln_init_recv_even_lfeature_req_ok) +{ + ln_channel_t channel; + LnInit(&channel); + + static const uint8_t LFEATURE[][2] = { + { 0x00, 0x01 }, //option_data_loss_protect + //{ 0x00, 0x04 }, //initial_routing_sync(no REQUIRE feature) + //{ 0x00, 0x10 }, //option_upfront_shutdown_script +#ifdef USE_GOSSIP_QUERY + { 0x00, 0x40 }, //gossip_queries +#endif + //{ 0x01, 0x00 }, //var_onion_optin + //{ 0x04, 0x00 }, //gossip_queries_ex + //{ 0x10, 0x00 }, //option_static_remotekey + //{ 0x40, 0x00 }, //RFU + }; + static const uint8_t *pLFeature; + class dummy { + public: + static bool ln_msg_init_read(ln_msg_init_t *pMsg, const uint8_t *pData, uint16_t Len) { + (void)pData; (void)Len; + pMsg->gflen = 0; + pMsg->p_globalfeatures = NULL; + pMsg->lflen = 2; + pMsg->p_localfeatures = pLFeature; + return true; + } + }; + ln_msg_init_read_fake.custom_fake = dummy::ln_msg_init_read; + + for (size_t lp = 0; lp < ARRAY_SIZE(LFEATURE); lp++) { + pLFeature = LFEATURE[lp]; + channel.init_flag = 0; + channel.lfeature_remote = 0; + //printf("[%d]%02x %02x\n", (int)lp, pLFeature[0], pLFeature[1]); + ASSERT_TRUE(ln_init_recv(&channel, NULL, 0)); + ASSERT_EQ(pLFeature[0], channel.lfeature_remote>>8); + ASSERT_EQ(pLFeature[1], channel.lfeature_remote & 0xff); + } +} + +TEST_F(ln, ln_init_recv_feature_lnd) +{ + ln_channel_t channel; + LnInit(&channel); + + static const uint8_t GFEATURE[] = { 0x22, 0x00 }; + static const uint8_t LFEATURE[] = { 0x22, 0x81 }; + class dummy { + public: + static bool ln_msg_init_read(ln_msg_init_t *pMsg, const uint8_t *pData, uint16_t Len) { + (void)pData; (void)Len; + pMsg->gflen = sizeof(GFEATURE); + pMsg->p_globalfeatures = GFEATURE; + pMsg->lflen = sizeof(LFEATURE); + pMsg->p_localfeatures = LFEATURE; + return true; + } + }; + ln_msg_init_read_fake.custom_fake = dummy::ln_msg_init_read; + + ASSERT_TRUE(ln_init_recv(&channel, NULL, 0)); + ASSERT_EQ(0x2281, channel.lfeature_remote); +} diff --git a/ln/tests/test_ln_proto_init.cpp b/ln/tests/test_ln_proto_init.cpp index dc3183cba..3ffd26155 100644 --- a/ln/tests/test_ln_proto_init.cpp +++ b/ln/tests/test_ln_proto_init.cpp @@ -346,3 +346,45 @@ TEST_F(ln, init_recv_lf1) ASSERT_TRUE(b_called); } } + + +TEST_F(ln, init_recv_lf2) +{ + ln_channel_t channel; + LnInit(&channel); + + static bool b_called; + static uint8_t lf[sizeof(uint16_t)]; + class dummy { + public: + static bool ln_msg_init_read(ln_msg_init_t *pMsg, const uint8_t *pData, uint16_t Len) { + pMsg->gflen = 0; + pMsg->lflen = sizeof(lf); + pMsg->p_localfeatures = lf; + return true; + } + static void callback(ln_cb_type_t Type, void *pCommonParam, void *pTypeSpecificParam) { + (void)pCommonParam; (void)pTypeSpecificParam; + if (Type == LN_CB_TYPE_NOTIFY_INIT_RECV) { + b_called = true; + } + } + }; + channel.p_callback = dummy::callback; + ln_msg_init_read_fake.custom_fake = dummy::ln_msg_init_read; + + bool ret; + + channel.init_flag = 0; + channel.lfeature_remote = 0; + b_called = false; + + lf[0] = 0xaa; + lf[1] = 0xaa; + ret = ln_init_recv(&channel, NULL, 0); + ASSERT_TRUE(ret); + ASSERT_EQ(lf[0], channel.lfeature_remote >> 8); + ASSERT_EQ(lf[1], channel.lfeature_remote & 0xff); + ASSERT_EQ(M_INIT_FLAG_RECV, channel.init_flag); + ASSERT_TRUE(b_called); +} diff --git a/ptarmd/conf.c b/ptarmd/conf.c index 7b8b545ed..6663c3c87 100644 --- a/ptarmd/conf.c +++ b/ptarmd/conf.c @@ -55,7 +55,11 @@ #define M_MIN_DEPTH (1) // init -#define M_LOCALFEATURES (LN_INIT_LF_OPT_DATALOSS) +#ifdef USE_GOSSIP_QUERY +#define M_LOCALFEATURES ((uint16_t)(LN_INIT_LF_OPT_DATALOSS | LN_INIT_LF_OPT_GSP_QUERY)) +#else +#define M_LOCALFEATURES ((uint16_t)LN_INIT_LF_OPT_DATALOSS) +#endif //USE_GOSSIP_QUERY // feerate #define M_FEERATE_MIN (0) #define M_FEERATE_MAX (0) @@ -329,7 +333,7 @@ static int handler_channel_conf(void* user, const char* section, const char* nam pconfig->min_depth = val; } } else if (strcmp(name, "localfeatures") == 0) { - pconfig->localfeatures = (uint8_t)strtoul(value, NULL, 10); + pconfig->localfeatures = (uint16_t)strtoul(value, NULL, 10); } else if (strcmp(name, "feerate_min") == 0) { pconfig->feerate_min = (uint16_t)strtoul(value, NULL, 10); } else if (strcmp(name, "feerate_max") == 0) { diff --git a/ptarmd/ptarmd.h b/ptarmd/ptarmd.h index 9521484df..abdeadb2e 100644 --- a/ptarmd/ptarmd.h +++ b/ptarmd/ptarmd.h @@ -250,7 +250,7 @@ typedef struct { uint16_t max_accepted_htlcs; ///< 2 : max-accepted-htlcs uint32_t min_depth; ///< 4 : minimum-depth(acceptのみ) - uint8_t localfeatures; ///< init.localfeatures + uint16_t localfeatures; ///< init.localfeatures uint16_t feerate_min; ///< feerate_per_kw limit min percent(0..all OK) uint16_t feerate_max; ///< feerate_per_kw limit max percent(0..all OK) } channel_conf_t; diff --git a/showdb/showdb.c b/showdb/showdb.c index 4b29d43cf..84134b45f 100644 --- a/showdb/showdb.c +++ b/showdb/showdb.c @@ -327,7 +327,7 @@ static void ln_print_channel(const ln_channel_t *pChannel) printf(INDENT3 "},\n"); //init - printf(INDENT3 M_QQ("lfeature_remote") ": " M_QQ("0x%02x") ",\n", pChannel->lfeature_remote); + //printf(INDENT3 M_QQ("lfeature_remote") ": " M_QQ("0x%04x") ",\n", pChannel->lfeature_remote); //close printf(INDENT3 M_QQ("close") ": {\n");