diff --git a/formats-gossip_queries_ex-and-static_remotekey.csv b/formats-gossip_queries_ex-and-static_remotekey.csv new file mode 100644 index 000000000..7777f7d5a --- /dev/null +++ b/formats-gossip_queries_ex-and-static_remotekey.csv @@ -0,0 +1,254 @@ +msgtype,init,16 +msgdata,init,gflen,u16, +msgdata,init,globalfeatures,byte,gflen +msgdata,init,lflen,u16, +msgdata,init,localfeatures,byte,lflen +msgtype,error,17 +msgdata,error,channel_id,channel_id, +msgdata,error,len,u16, +msgdata,error,data,byte,len +msgtype,ping,18 +msgdata,ping,num_pong_bytes,u16, +msgdata,ping,byteslen,u16, +msgdata,ping,ignored,byte,byteslen +msgtype,pong,19 +msgdata,pong,byteslen,u16, +msgdata,pong,ignored,byte,byteslen +tlvtype,n1,tlv1,1 +tlvdata,n1,tlv1,amount_msat,tu64, +tlvtype,n1,tlv2,2 +tlvdata,n1,tlv2,scid,short_channel_id, +tlvtype,n1,tlv3,3 +tlvdata,n1,tlv3,node_id,point, +tlvdata,n1,tlv3,amount_msat_1,u64, +tlvdata,n1,tlv3,amount_msat_2,u64, +tlvtype,n1,tlv4,254 +tlvdata,n1,tlv4,cltv_delta,u16, +tlvtype,n2,tlv1,0 +tlvdata,n2,tlv1,amount_msat,tu64, +tlvtype,n2,tlv2,11 +tlvdata,n2,tlv2,cltv_expiry,tu32, +msgtype,open_channel,32 +msgdata,open_channel,chain_hash,chain_hash, +msgdata,open_channel,temporary_channel_id,byte,32 +msgdata,open_channel,funding_satoshis,u64, +msgdata,open_channel,push_msat,u64, +msgdata,open_channel,dust_limit_satoshis,u64, +msgdata,open_channel,max_htlc_value_in_flight_msat,u64, +msgdata,open_channel,channel_reserve_satoshis,u64, +msgdata,open_channel,htlc_minimum_msat,u64, +msgdata,open_channel,feerate_per_kw,u32, +msgdata,open_channel,to_self_delay,u16, +msgdata,open_channel,max_accepted_htlcs,u16, +msgdata,open_channel,funding_pubkey,point, +msgdata,open_channel,revocation_basepoint,point, +msgdata,open_channel,payment_basepoint,point, +msgdata,open_channel,delayed_payment_basepoint,point, +msgdata,open_channel,htlc_basepoint,point, +msgdata,open_channel,first_per_commitment_point,point, +msgdata,open_channel,channel_flags,byte, +msgdata,open_channel,shutdown_len,u16,,option_upfront_shutdown_script +msgdata,open_channel,shutdown_scriptpubkey,byte,shutdown_len,option_upfront_shutdown_script +msgtype,accept_channel,33 +msgdata,accept_channel,temporary_channel_id,byte,32 +msgdata,accept_channel,dust_limit_satoshis,u64, +msgdata,accept_channel,max_htlc_value_in_flight_msat,u64, +msgdata,accept_channel,channel_reserve_satoshis,u64, +msgdata,accept_channel,htlc_minimum_msat,u64, +msgdata,accept_channel,minimum_depth,u32, +msgdata,accept_channel,to_self_delay,u16, +msgdata,accept_channel,max_accepted_htlcs,u16, +msgdata,accept_channel,funding_pubkey,point, +msgdata,accept_channel,revocation_basepoint,point, +msgdata,accept_channel,payment_basepoint,point, +msgdata,accept_channel,delayed_payment_basepoint,point, +msgdata,accept_channel,htlc_basepoint,point, +msgdata,accept_channel,first_per_commitment_point,point, +msgdata,accept_channel,shutdown_len,u16,,option_upfront_shutdown_script +msgdata,accept_channel,shutdown_scriptpubkey,byte,shutdown_len,option_upfront_shutdown_script +msgtype,funding_created,34 +msgdata,funding_created,temporary_channel_id,byte,32 +msgdata,funding_created,funding_txid,sha256, +msgdata,funding_created,funding_output_index,u16, +msgdata,funding_created,signature,signature, +msgtype,funding_signed,35 +msgdata,funding_signed,channel_id,channel_id, +msgdata,funding_signed,signature,signature, +msgtype,funding_locked,36 +msgdata,funding_locked,channel_id,channel_id, +msgdata,funding_locked,next_per_commitment_point,point, +msgtype,shutdown,38 +msgdata,shutdown,channel_id,channel_id, +msgdata,shutdown,len,u16, +msgdata,shutdown,scriptpubkey,byte,len +msgtype,closing_signed,39 +msgdata,closing_signed,channel_id,channel_id, +msgdata,closing_signed,fee_satoshis,u64, +msgdata,closing_signed,signature,signature, +msgtype,update_add_htlc,128 +msgdata,update_add_htlc,channel_id,channel_id, +msgdata,update_add_htlc,id,u64, +msgdata,update_add_htlc,amount_msat,u64, +msgdata,update_add_htlc,payment_hash,sha256, +msgdata,update_add_htlc,cltv_expiry,u32, +msgdata,update_add_htlc,onion_routing_packet,byte,1366 +msgtype,update_fulfill_htlc,130 +msgdata,update_fulfill_htlc,channel_id,channel_id, +msgdata,update_fulfill_htlc,id,u64, +msgdata,update_fulfill_htlc,payment_preimage,byte,32 +msgtype,update_fail_htlc,131 +msgdata,update_fail_htlc,channel_id,channel_id, +msgdata,update_fail_htlc,id,u64, +msgdata,update_fail_htlc,len,u16, +msgdata,update_fail_htlc,reason,byte,len +msgtype,update_fail_malformed_htlc,135 +msgdata,update_fail_malformed_htlc,channel_id,channel_id, +msgdata,update_fail_malformed_htlc,id,u64, +msgdata,update_fail_malformed_htlc,sha256_of_onion,sha256, +msgdata,update_fail_malformed_htlc,failure_code,u16, +msgtype,commitment_signed,132 +msgdata,commitment_signed,channel_id,channel_id, +msgdata,commitment_signed,signature,signature, +msgdata,commitment_signed,num_htlcs,u16, +msgdata,commitment_signed,htlc_signature,signature,num_htlcs +msgtype,revoke_and_ack,133 +msgdata,revoke_and_ack,channel_id,channel_id, +msgdata,revoke_and_ack,per_commitment_secret,byte,32 +msgdata,revoke_and_ack,next_per_commitment_point,point, +msgtype,update_fee,134 +msgdata,update_fee,channel_id,channel_id, +msgdata,update_fee,feerate_per_kw,u32, +msgtype,channel_reestablish,136 +msgdata,channel_reestablish,channel_id,channel_id, +msgdata,channel_reestablish,next_commitment_number,u64, +msgdata,channel_reestablish,next_revocation_number,u64, +msgdata,channel_reestablish,your_last_per_commitment_secret,byte,32,option_data_loss_protect,option_static_remotekey +msgdata,channel_reestablish,my_current_per_commitment_point,point,,option_data_loss_protect +tlvtype,tlv_payload,amt_to_forward,2 +tlvdata,tlv_payload,amt_to_forward,amt_to_forward,tu64, +tlvtype,tlv_payload,outgoing_cltv_value,4 +tlvdata,tlv_payload,outgoing_cltv_value,outgoing_cltv_value,tu32, +tlvtype,tlv_payload,short_channel_id,6 +tlvdata,tlv_payload,short_channel_id,short_channel_id,short_channel_id, +msgtype,invalid_realm,PERM|1 +msgtype,temporary_node_failure,NODE|2 +msgtype,permanent_node_failure,PERM|NODE|2 +msgtype,required_node_feature_missing,PERM|NODE|3 +msgtype,invalid_onion_version,BADONION|PERM|4 +msgdata,invalid_onion_version,sha256_of_onion,sha256, +msgtype,invalid_onion_hmac,BADONION|PERM|5 +msgdata,invalid_onion_hmac,sha256_of_onion,sha256, +msgtype,invalid_onion_key,BADONION|PERM|6 +msgdata,invalid_onion_key,sha256_of_onion,sha256, +msgtype,temporary_channel_failure,UPDATE|7 +msgdata,temporary_channel_failure,len,u16, +msgdata,temporary_channel_failure,channel_update,byte,len +msgtype,permanent_channel_failure,PERM|8 +msgtype,required_channel_feature_missing,PERM|9 +msgtype,unknown_next_peer,PERM|10 +msgtype,amount_below_minimum,UPDATE|11 +msgdata,amount_below_minimum,htlc_msat,u64, +msgdata,amount_below_minimum,len,u16, +msgdata,amount_below_minimum,channel_update,byte,len +msgtype,fee_insufficient,UPDATE|12 +msgdata,fee_insufficient,htlc_msat,u64, +msgdata,fee_insufficient,len,u16, +msgdata,fee_insufficient,channel_update,byte,len +msgtype,incorrect_cltv_expiry,UPDATE|13 +msgdata,incorrect_cltv_expiry,cltv_expiry,u32, +msgdata,incorrect_cltv_expiry,len,u16, +msgdata,incorrect_cltv_expiry,channel_update,byte,len +msgtype,expiry_too_soon,UPDATE|14 +msgdata,expiry_too_soon,len,u16, +msgdata,expiry_too_soon,channel_update,byte,len +msgtype,incorrect_or_unknown_payment_details,PERM|15 +msgdata,incorrect_or_unknown_payment_details,htlc_msat,u64, +msgtype,final_expiry_too_soon,17 +msgtype,final_incorrect_cltv_expiry,18 +msgdata,final_incorrect_cltv_expiry,cltv_expiry,u32, +msgtype,final_incorrect_htlc_amount,19 +msgdata,final_incorrect_htlc_amount,incoming_htlc_amt,u64, +msgtype,channel_disabled,UPDATE|20 +msgtype,expiry_too_far,21 +msgtype,announcement_signatures,259 +msgdata,announcement_signatures,channel_id,channel_id, +msgdata,announcement_signatures,short_channel_id,short_channel_id, +msgdata,announcement_signatures,node_signature,signature, +msgdata,announcement_signatures,bitcoin_signature,signature, +msgtype,channel_announcement,256 +msgdata,channel_announcement,node_signature_1,signature, +msgdata,channel_announcement,node_signature_2,signature, +msgdata,channel_announcement,bitcoin_signature_1,signature, +msgdata,channel_announcement,bitcoin_signature_2,signature, +msgdata,channel_announcement,len,u16, +msgdata,channel_announcement,features,byte,len +msgdata,channel_announcement,chain_hash,chain_hash, +msgdata,channel_announcement,short_channel_id,short_channel_id, +msgdata,channel_announcement,node_id_1,point, +msgdata,channel_announcement,node_id_2,point, +msgdata,channel_announcement,bitcoin_key_1,point, +msgdata,channel_announcement,bitcoin_key_2,point, +msgtype,node_announcement,257 +msgdata,node_announcement,signature,signature, +msgdata,node_announcement,flen,u16, +msgdata,node_announcement,features,byte,flen +msgdata,node_announcement,timestamp,u32, +msgdata,node_announcement,node_id,point, +msgdata,node_announcement,rgb_color,byte,3 +msgdata,node_announcement,alias,byte,32 +msgdata,node_announcement,addrlen,u16, +msgdata,node_announcement,addresses,byte,addrlen +msgtype,channel_update,258 +msgdata,channel_update,signature,signature, +msgdata,channel_update,chain_hash,chain_hash, +msgdata,channel_update,short_channel_id,short_channel_id, +msgdata,channel_update,timestamp,u32, +msgdata,channel_update,message_flags,byte, +msgdata,channel_update,channel_flags,byte, +msgdata,channel_update,cltv_expiry_delta,u16, +msgdata,channel_update,htlc_minimum_msat,u64, +msgdata,channel_update,fee_base_msat,u32, +msgdata,channel_update,fee_proportional_millionths,u32, +msgdata,channel_update,htlc_maximum_msat,u64,,option_channel_htlc_max +msgtype,query_short_channel_ids,261,gossip_queries +msgdata,query_short_channel_ids,chain_hash,chain_hash, +msgdata,query_short_channel_ids,len,u16, +msgdata,query_short_channel_ids,encoded_short_ids,byte,len +msgdata,query_short_channel_ids,tlvs,query_short_channel_ids_tlvs, +tlvtype,query_short_channel_ids_tlvs,query_flags,1 +tlvdata,query_short_channel_ids_tlvs,query_flags,encoding_type,byte, +tlvdata,query_short_channel_ids_tlvs,query_flags,encoded_query_flags,byte,... +msgtype,reply_short_channel_ids_end,262,gossip_queries +msgdata,reply_short_channel_ids_end,chain_hash,chain_hash, +msgdata,reply_short_channel_ids_end,complete,byte, +msgtype,query_channel_range,263,gossip_queries +msgdata,query_channel_range,chain_hash,chain_hash, +msgdata,query_channel_range,first_blocknum,u32, +msgdata,query_channel_range,number_of_blocks,u32, +msgdata,query_channel_range,tlvs,query_channel_range_tlvs, +tlvtype,query_channel_range_tlvs,query_option,1 +tlvdata,query_channel_range_tlvs,query_option,query_option_flags,varint, +msgtype,reply_channel_range,264,gossip_queries +msgdata,reply_channel_range,chain_hash,chain_hash, +msgdata,reply_channel_range,first_blocknum,u32, +msgdata,reply_channel_range,number_of_blocks,u32, +msgdata,reply_channel_range,complete,byte, +msgdata,reply_channel_range,len,u16, +msgdata,reply_channel_range,encoded_short_ids,byte,len +msgdata,reply_channel_range,tlvs,reply_channel_range_tlvs, +tlvtype,reply_channel_range_tlvs,timestamps_tlv,1 +tlvdata,reply_channel_range_tlvs,timestamps_tlv,encoding_type,byte, +tlvdata,reply_channel_range_tlvs,timestamps_tlv,encoded_timestamps,byte,... +tlvtype,reply_channel_range_tlvs,checksums_tlv,3 +tlvdata,reply_channel_range_tlvs,checksums_tlv,encoding_type,byte, +tlvdata,reply_channel_range_tlvs,checksums_tlv,encoded_checksums,byte,... +subtype,channel_update_timestamps +subtypedata,channel_update_timestamps,timestamp_node_id_1,u32, +subtypedata,channel_update_timestamps,timestamp_node_id_2,u32, +subtype,channel_update_checksums +subtypedata,channel_update_checksums,checksum_node_id_1,u32, +subtypedata,channel_update_checksums,checksum_node_id_2,u32, +msgtype,gossip_timestamp_filter,265,gossip_queries +msgdata,gossip_timestamp_filter,chain_hash,chain_hash, +msgdata,gossip_timestamp_filter,first_timestamp,u32, +msgdata,gossip_timestamp_filter,timestamp_range,u32, diff --git a/tests/events/README.md b/tests/events/README.md new file mode 100644 index 000000000..470ea8679 --- /dev/null +++ b/tests/events/README.md @@ -0,0 +1,23 @@ +# Implementation Tests for Lightning Specifications + +This directory contains conversation-style tests for Lightning +implementations. The format is documented in +[tests/events/test-spec.md](events/test-spec.md), and the base driver for an +implementation is in the [tools/test-events.py](../tools/test-events.py). + +To run the tests, you need to write a driver for your particular +implementation, like the one for +[c-lightning](../tools/test-events-clightning.py). Then extract the +format of all messages into a file, like so: + + $ python3 tools/extract-formats.py 0*.md > format.csv + +Finally, you can run a test like so: + + $ tools/test-events-clightning.py formats.csv tests/events/*.events + +The `-v` option will give more verbose output, which is particularly +useful when debugging your test script. + +Good luck! +Rusty. diff --git a/tests/events/bolt1-01-init.events b/tests/events/bolt1-01-init.events new file mode 100644 index 000000000..399fe9aa6 --- /dev/null +++ b/tests/events/bolt1-01-init.events @@ -0,0 +1,75 @@ +# Variations on init exchange. +# Spec: MUST respond to known feature bits as specified in [BOLT #9](09-features.md). + +1. connect: privkey=0000000000000000000000000000000000000000000000000000000000000003 +2. expect-send: type=init +3. recv: type=init globalfeatures= localfeatures= + + 1. nothing + 1. disconnect: + +4. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + # Even if we don't send anything, it should send init. + 1. expect-send: type=init + + # Minimal possible init message. + # Spec: MUST send `init` as the first Lightning message for any connection. + 1. expect-send: type=init + 2. recv: type=init globalfeatures= localfeatures= + + # Sanity check that bits 14 and 15 are not used! + 1. expect-send: type=init globalfeatures=0000/C000 + # init msg with unknown odd global bit (15): no error + 2. recv: type=init globalfeatures=8000 localfeatures= + + 1. expect-send: type=init localfeatures=0000/C000 + # init msg with unknown odd local bit (15): no error + 2. recv: type=init globalfeatures= localfeatures=8000 + + # init msg with unknown even global bit (14): you will error + 1. expect-send: type=init + 2. recv: type=init globalfeatures=4000 localfeatures= + 3. expect-error: + + # init msg with unknown even local bit (14): you will error + 1. expect-send: type=init + 2. recv: type=init globalfeatures= localfeatures=4000 + 3. expect-error: + + # If you don't support `option_data_loss_protect`, you will be ok if + # we ask for it. + 1. expect-send: type=init localfeatures=00/03 !option_data_loss_protect + 2. recv: type=init globalfeatures= localfeatures=02 !option_data_loss_protect + + # If you don't support `option_data_loss_protect`, you will error if + # we require it. + 1. expect-send: type=init localfeatures=00/03 !option_data_loss_protect + 2. recv: type=init globalfeatures= localfeatures=01 !option_data_loss_protect + 3. expect-error: !option_data_loss_protect + + # If you support `option_data_loss_protect`, you will advertize it odd. + 1. expect-send: type=init localfeatures=02/03 option_data_loss_protect/odd + + # If you require `option_data_loss_protect`, you will advertize it even. + 1. expect-send: type=init localfeatures=01/03 option_data_loss_protect/even + + # If you don't support `option_static_remotekey`, you will be ok if + # we ask for it. + 1. expect-send: type=init localfeatures=0000000000/C000000000 !option_static_remotekey + 2. recv: type=init globalfeatures= localfeatures=02000000000000 !option_static_remotekey + + # If you don't support `option_static_remotekey`, you will error if + # we require it. + 1. expect-send: type=init localfeatures=0000000000/C000000000 !option_static_remotekey + 2. recv: type=init globalfeatures= localfeatures=01000000000000 !option_static_remotekey + 3. expect-error: !option_static_remotekey + + # If you support `option_static_remotekey`, you will advertize it odd. + 1. expect-send: type=init localfeatures=02000000000000/03000000000000 option_static_remotekey/odd + + # If you require `option_static_remotekey`, you will advertize it even. + 1. expect-send: type=init localfeatures=01000000000000/03000000000000 option_static_remotekey/even + + # Note: it's undefined what you'll do if implementation requires + # an option and isn't offered it. The recipient of the required feature + # bit should notice the requirement and error. diff --git a/tests/events/bolt1-02-unknown-messages.events b/tests/events/bolt1-02-unknown-messages.events new file mode 100644 index 000000000..8881aa36d --- /dev/null +++ b/tests/events/bolt1-02-unknown-messages.events @@ -0,0 +1,22 @@ +# Init exchange, with unknown messages +# +# BOLT #1: +# The receiving node: +#... +# - upon receiving unknown _odd_ feature bits that are non-zero: +# - MUST ignore the bit. +# - upon receiving unknown _even_ feature bits that are non-zero: +# - MUST fail the connection. + +1. connect: privkey=0000000000000000000000000000000000000000000000000000000000000003 +2. expect-send: type=init +3. recv: type=init globalfeatures= localfeatures= + + 1. nothing + + # Unknown odd is OK. + 1. recv: type=9999 + + # Unknown even causes error. + 1. recv: type=10000 + 2. expect-error: diff --git a/tests/events/bolt2-01-open_channel.events b/tests/events/bolt2-01-open_channel.events new file mode 100644 index 000000000..40b269baf --- /dev/null +++ b/tests/events/bolt2-01-open_channel.events @@ -0,0 +1,95 @@ +# Variations on open_channel. +# +include setup.incl + +1. block: $BLOCK_102 + +2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 +3. expect-send: type=init +4. recv: type=init globalfeatures= localfeatures= + + # We assume a funding_per_kw=253 Satoshi/kSipa. + # This gives a channel of 999878sat + 1. recv: type=open_channel + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + temporary_channel_id=0000000000000000000000000000000000000000000000000000000000000000 + funding_satoshis=999878 + push_msat=0 + dust_limit_satoshis=546 + max_htlc_value_in_flight_msat=4294967295 + channel_reserve_satoshis=9998 + htlc_minimum_msat=0 + feerate_per_kw=253 + to_self_delay=6 + max_accepted_htlcs=483 + # funding_privkey=0000000000000000000000000000000000000000000000000000000000000020 + funding_pubkey=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 + # revocation_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000021 + revocation_basepoint=021697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5 + # payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000022 + payment_basepoint=031be68a5a028f2601d0e80d468c344ba331d611b96c358b6032e8b4da0547fc11 + # delayed_payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000023 + delayed_payment_basepoint=03605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479 + # htlc_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000024 + htlc_basepoint=02e0392cfa338aaf2f0b56c563e3e5e67a5d5fefe3388f85d90c899da20f0198f9 + # shachain seed=0000000000000000000000000000000000000000000000000000000000000000 + # first per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 + first_per_commitment_point=02037803a3228ec3a517835480ffac64c0557d9d75e0fe85861ab0be9eb224e6f8 + channel_flags=01 + + # Ignore unknown odd messages + 1. nothing + 1. recv: type=9999 + + 2. expect-send: type=accept_channel + temporary_channel_id=0000000000000000000000000000000000000000000000000000000000000000 + # funding_privkey=0000000000000000000000000000000000000000000000000000000000000010 + funding_pubkey=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + # revocation_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000011 + revocation_basepoint=03defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34 + # payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000012 + payment_basepoint=025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc + # delayed_payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000013 + delayed_payment_basepoint=022b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c + # htlc_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000014 + htlc_basepoint=024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97 + # shachain seed=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + # first per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc + first_per_commitment_point=0288a618cb6027c3218a37cbe9e882379f17d87d03f6e99d0b60292478d2aded06 + minimum_depth=3 + # If these are different, the commitment tx will be different! + to_self_delay=6 + channel_reserve_satoshis=9998 + + # Ignore unknown messages + 1. nothing + 1. recv: type=9999 + + 3. recv: type=funding_created + temporary_channel_id=0000000000000000000000000000000000000000000000000000000000000000 + # Funding tx is 020000000001016b85f654d8186f4d5dd32a977b2cf8c4b01ff4634152acba16b654c1c85a83160100000000ffffffff01c6410f0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738202473044022047e9e6e798ba9adb6c84bdcd6230a96fb6de9dcca84d81103fb2bc08906cb884022027599b1e80289eaf238e9a00119a79a0ccceab7d83d54719e10bd0c3300a0d34012102d6a3c2d0cf7904ab6af54d7c959435a452b24a63194e1c4e7c337d3ebbb3017b00000000 + # txid=41085b995c1f591cfc3ae79ccde012bf0b37c7bde23d80a61c9732bdd6210b2f + funding_txid=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + funding_output_index=0 + # node's commitment tx is 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a980010f410f0000000000160014749af8703f0d1fd8890a553bd62e9caf15f7bad44cff0020 + signature=c0c95040f0c132b5773b05fcc59e4a394059db70e6767567f26cbceecc580bcf27da384471a5efdaabd04090dd1d5c3765e849e5fdfe556eabba1ebca806b02a + + 4. expect-send: type=funding_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + # test's commitment tx is 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a980010f410f0000000000220020233d69d88092351875ce0b9fd5ea576b2307c539eaed7abdf97fbb26720f01ac4cff0020 + signature=0adfc07a0168630b2e216aa8068dc8aa353be4b622a32ea7629f6d92c37dddcb1f1d605e686d4f49435f415dd9d76174b96b33c7c3e0d5f4eb1d0a9953ad95a1 + + 5. block: height=103 n=3 tx=020000000001016b85f654d8186f4d5dd32a977b2cf8c4b01ff4634152acba16b654c1c85a83160100000000ffffffff01c6410f0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738202473044022047e9e6e798ba9adb6c84bdcd6230a96fb6de9dcca84d81103fb2bc08906cb884022027599b1e80289eaf238e9a00119a79a0ccceab7d83d54719e10bd0c3300a0d34012102d6a3c2d0cf7904ab6af54d7c959435a452b24a63194e1c4e7c337d3ebbb3017b00000000 + + 6. expect-send: type=funding_locked + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 + + 7. recv: type=funding_locked + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_per_commitment_point=027eed8389cf8eb715d73111b73d94d2c2d04bf96dc43dfd5b0970d80b3617009d + + # Ignore unknown odd messages + 1. nothing + 1. recv: type=9999 + diff --git a/tests/events/bolt2-02-add-htlc.events b/tests/events/bolt2-02-add-htlc.events new file mode 100644 index 000000000..c40efd411 --- /dev/null +++ b/tests/events/bolt2-02-add-htlc.events @@ -0,0 +1,528 @@ +# Variations on adding an HTLC. + +# BOLT #7: +# The origin node: +# - MAY create a `channel_update` to communicate the channel +# parameters to the channel peer, even though the channel has not +# yet been announced (i.e. the `announce_channel` bit was not set). + +# In fact, it makes sense to do this after each reconnect. +MAYBE_UPDATE=maybe-send: type=channel_update + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + # FIXME: Fill other expected fields here! + +include setup.incl + +1. block: $BLOCK_102 + +2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 +3. expect-send: type=init +4. recv: type=init globalfeatures= localfeatures=02000000000002 +5. recv: type=open_channel + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + temporary_channel_id=0000000000000000000000000000000000000000000000000000000000000000 + funding_satoshis=999878 + push_msat=0 + dust_limit_satoshis=546 + max_htlc_value_in_flight_msat=4294967295 + channel_reserve_satoshis=9998 + htlc_minimum_msat=0 + feerate_per_kw=253 + # node has to_self_delay=6; we use 5 to test differentiation + to_self_delay=5 + max_accepted_htlcs=483 + # funding_privkey=0000000000000000000000000000000000000000000000000000000000000020 + funding_pubkey=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 + # revocation_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000021 + revocation_basepoint=021697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5 + # payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000022 + payment_basepoint=031be68a5a028f2601d0e80d468c344ba331d611b96c358b6032e8b4da0547fc11 + # delayed_payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000023 + delayed_payment_basepoint=03605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479 + # htlc_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000024 + htlc_basepoint=02e0392cfa338aaf2f0b56c563e3e5e67a5d5fefe3388f85d90c899da20f0198f9 + # shachain seed=0000000000000000000000000000000000000000000000000000000000000000 + # first per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 + first_per_commitment_point=02037803a3228ec3a517835480ffac64c0557d9d75e0fe85861ab0be9eb224e6f8 + channel_flags=01 + +6. expect-send: type=accept_channel + temporary_channel_id=0000000000000000000000000000000000000000000000000000000000000000 + # funding_privkey=0000000000000000000000000000000000000000000000000000000000000010 + funding_pubkey=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + # revocation_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000011 + revocation_basepoint=03defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34 + # payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000012 + payment_basepoint=025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc + # delayed_payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000013 + delayed_payment_basepoint=022b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c + # htlc_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000014 + htlc_basepoint=024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97 + # shachain seed=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + # per_commitment_secret #0=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc + first_per_commitment_point=0288a618cb6027c3218a37cbe9e882379f17d87d03f6e99d0b60292478d2aded06 + # If these are different, the commitment tx will be different! + to_self_delay=6 + channel_reserve_satoshis=9998 + +7. recv: type=funding_created + temporary_channel_id=0000000000000000000000000000000000000000000000000000000000000000 + # Funding tx is 020000000001016b85f654d8186f4d5dd32a977b2cf8c4b01ff4634152acba16b654c1c85a83160100000000ffffffff01c6410f0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738202473044022047e9e6e798ba9adb6c84bdcd6230a96fb6de9dcca84d81103fb2bc08906cb884022027599b1e80289eaf238e9a00119a79a0ccceab7d83d54719e10bd0c3300a0d34012102d6a3c2d0cf7904ab6af54d7c959435a452b24a63194e1c4e7c337d3ebbb3017b00000000 + # txid=41085b995c1f591cfc3ae79ccde012bf0b37c7bde23d80a61c9732bdd6210b2f + funding_txid=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + funding_output_index=0 + # !option_static_remotekey: node's commitment tx is 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a980010f410f0000000000160014749af8703f0d1fd8890a553bd62e9caf15f7bad44cff0020 + signature=c0c95040f0c132b5773b05fcc59e4a394059db70e6767567f26cbceecc580bcf27da384471a5efdaabd04090dd1d5c3765e849e5fdfe556eabba1ebca806b02a !option_static_remotekey + # option_static_remotekey: node's commitment tx is 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a980010f410f0000000000160014e142ca9bfc2d56cd0adb82f8dc870424767389f74cff0020 + signature=02ce278a17c48e926f93d5134e8f7486e01112a7d06c2ed1b1b5034fb9ace8072d1485ee012440fc85b46cf671a802db4597d482ced68dbfa26ee07b899e936a option_static_remotekey + +8. expect-send: type=funding_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + # test's commitment tx is 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a980010f410f0000000000220020233d69d88092351875ce0b9fd5ea576b2307c539eaed7abdf97fbb26720f01ac4cff0020 + signature=0adfc07a0168630b2e216aa8068dc8aa353be4b622a32ea7629f6d92c37dddcb1f1d605e686d4f49435f415dd9d76174b96b33c7c3e0d5f4eb1d0a9953ad95a1 + +9. block: height=103 n=3 tx=020000000001016b85f654d8186f4d5dd32a977b2cf8c4b01ff4634152acba16b654c1c85a83160100000000ffffffff01c6410f0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738202473044022047e9e6e798ba9adb6c84bdcd6230a96fb6de9dcca84d81103fb2bc08906cb884022027599b1e80289eaf238e9a00119a79a0ccceab7d83d54719e10bd0c3300a0d34012102d6a3c2d0cf7904ab6af54d7c959435a452b24a63194e1c4e7c337d3ebbb3017b00000000 + +10. expect-send: type=funding_locked + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 + +11. recv: type=funding_locked + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + # per_commitment_secret #1 = dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3 + next_per_commitment_point=027eed8389cf8eb715d73111b73d94d2c2d04bf96dc43dfd5b0970d80b3617009d + +12. $MAYBE_UPDATE + + # Optional reconnection testing. + 1. nothing + + # Ignore unknown odd messages + 1. recv: type=9999 + + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + # Note: if we opened channel with option_static_remotekey, it stands even + # if we don't negotiate it again! + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=1 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=0288a618cb6027c3218a37cbe9e882379f17d87d03f6e99d0b60292478d2aded06 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=1 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02037803a3228ec3a517835480ffac64c0557d9d75e0fe85861ab0be9eb224e6f8 option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + # BOLT #2: + # - if `next_commitment_number` is 1 in both the + # `channel_reestablish` it sent and received: + # - MUST retransmit `funding_locked`. + # - otherwise: + # - MUST NOT retransmit `funding_locked`. + 8. expect-send: type=funding_locked + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 + +# That aside has nothing to do with the next aside. +13. nothing + +# Add a dust HTLC + 1. recv: type=update_add_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=0 + amount_msat=1000 + # preimage=0000000000000000000000000000000000000000000000000000000000000000 + payment_hash=66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925 + cltv_expiry=200 + # hop_data[0] = 00000000000000000000000000000003E8000000C8000000000000000000000000 + onion_routing_packet=0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619b1153ae94698ea83a3298ab3c0ddd9f755853e4e5fbc5d4f3cb457bbb74a9b81d3b5bc9cf42d8617d1fe6966ffb66b8ec0eaa1188865957e26df123d11705395d339472bcc4920e428492f7822424eef8e6d903a768ec01959f3a1f2c1cd8725ba13329df3a932f641dee600dbb1a9f3bbe93a167410961f1777a7b48679d8a3041d57c0b8e795ed4884fbb33a2564d4cdafb528c7b63fc31cd2739e71d1d3b56f35ba7976a373b883eed8f1f263aedd540cce9b548e53e58c32ab604195f6004d8d92fe0a9a454229b9bc0795f3e4ccd54089075483afaa0ef3b32ee12cf321052f7b9e5ac1c28169e57d5628c3aee5c775d5fb33ba835fda195981b1e3a06792bdd0ecf85f8f6107fd830ca932e92c6713ea6d4d5129395f54aeabb54debccca130ad019a1f53a20c0c46dd8625ada068e2a13ea5373b60ecdf412728cc78192ae1a56bae26dfb450d2f6b4905e6bd9843fda7df63eb11fb77ce995b25d3076210eca527bb556b4ddc564fa4c6ccb43f1149163a4959ffe4178d653d35bdc052e4a46dd58b8f95fde83d114c4e35fd02e94a0dd2a9ae21594184808074a57d9de30c5105b53efe03aca192f8c518bc2b9e13211a9761c1948b31aa97f99da449968380005f96ff49a6e5fe833220a82f358eb94197584b2dfa5a1efee8918b5020f028748e5897bb694979f580ff58b8b1d865783340eaff2d1ce738409ec1c62c1bd7f632cf0730a5634a1a2d91244b865302339c1861655e11b264aeaf2feefbf2d1222bb13c6bd6b2d2379d9a548f93de4d2a044928458eafa745021e0a69796bb40f17c1ca53b895c76b53924faa886a4a19f07b50eda5f316e5f3b5422e984c59928144c275d4ae5e78634e16c6dafcfc92bb302c7d5eef1456250b0b8a41f0cabb55dd114d6b0bcaf53ef1ee2185d2383df57a0f1bc21d31f5d3ae395bab6e77370ee83ffe8995e9bfbe2f90b3ff0578720e0584e969479d40327415835579d7b8885037c02a611292c6bbffde25e86c184cc7c7481e8856ce6a3cf7109a6c001e51a2289c5ee3633936578d4dc3de82c18ebb787bf2c475e8fa0393727cbdbcd36849ee0b7411fba6fd5cb8459e63aaf3fba7a4cd4a04b266d8f416f0586e2093ea9c210140a6e6cb72759ae1dee7c24497f68389fb8d154f927cc4ab59b9137652eaf9c7cb56f0cce6c58616646c6fee836b07ce738a965b1ea725d9960c47e61086be053f3e9c48c08ce945404b060d9e699ad962c910208dda42d665f8eacf9865a64d2612ea62e0e2c0a4c731b35ae87b04e45739c34f4c972ce433a2094b10a9601e6711b95a6a226a85f4e4ed0e0417dbc9d737cd7d3513a82943de94ff8e4c9e91838506283f4878e3f41488fec47198b4a262b55d3691d275c6154d2a2ce9ee6ab97087e0f33654b01450869797c993dfca76cd732677bf1856f43d040d68022055987588f64af357bea80491b4bc42341dd6f81631d30fc28e8c5d7e3312655b30d277f10ce76c2525279ad53157b1c2c78b412107fc5f974ac7946bdc33ee54d71f3fc261530d50f20813e4e6aadf39e67573d5dc93a45023edf297b56def6b14ec5e19ca10fbfd1b807f17fa983bec363cf495c708a581db1bba1a23730ce22d0f925d764b04be014d662c3a36ac58b015317c9cf5ca6464f2ecef15e1769f2c91922968532bda66e9aaa2a7f120a9301f563fd33db8e90c940984b0a297e0c595544b7f687476325a07dbaba255c8461e98f069eea2246cfa50f1c2ef8d4c54f5fd509a9cc839548d7c252e60bb9c165d05f30bd525f6b53a4c8afc8fc31026686bcd5a48172593941b3113cbed88e6cfb566f7a693bb63c9a89925c1f5df0a115b4893128866a81c1b + + # Optional reconnection testing. + 1. nothing + + # Ignore unknown odd messages + 1. recv: type=9999 + + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=1 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=0288a618cb6027c3218a37cbe9e882379f17d87d03f6e99d0b60292478d2aded06 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=1 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02037803a3228ec3a517835480ffac64c0557d9d75e0fe85861ab0be9eb224e6f8 option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + 8. expect-send: type=funding_locked + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 + 9. recv: type=update_add_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=0 + amount_msat=1000 + # preimage=0000000000000000000000000000000000000000000000000000000000000000 + payment_hash=66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925 + cltv_expiry=200 + # hop_data[0] = 00000000000000000000000000000003E8000000C8000000000000000000000000 + onion_routing_packet=0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619b1153ae94698ea83a3298ab3c0ddd9f755853e4e5fbc5d4f3cb457bbb74a9b81d3b5bc9cf42d8617d1fe6966ffb66b8ec0eaa1188865957e26df123d11705395d339472bcc4920e428492f7822424eef8e6d903a768ec01959f3a1f2c1cd8725ba13329df3a932f641dee600dbb1a9f3bbe93a167410961f1777a7b48679d8a3041d57c0b8e795ed4884fbb33a2564d4cdafb528c7b63fc31cd2739e71d1d3b56f35ba7976a373b883eed8f1f263aedd540cce9b548e53e58c32ab604195f6004d8d92fe0a9a454229b9bc0795f3e4ccd54089075483afaa0ef3b32ee12cf321052f7b9e5ac1c28169e57d5628c3aee5c775d5fb33ba835fda195981b1e3a06792bdd0ecf85f8f6107fd830ca932e92c6713ea6d4d5129395f54aeabb54debccca130ad019a1f53a20c0c46dd8625ada068e2a13ea5373b60ecdf412728cc78192ae1a56bae26dfb450d2f6b4905e6bd9843fda7df63eb11fb77ce995b25d3076210eca527bb556b4ddc564fa4c6ccb43f1149163a4959ffe4178d653d35bdc052e4a46dd58b8f95fde83d114c4e35fd02e94a0dd2a9ae21594184808074a57d9de30c5105b53efe03aca192f8c518bc2b9e13211a9761c1948b31aa97f99da449968380005f96ff49a6e5fe833220a82f358eb94197584b2dfa5a1efee8918b5020f028748e5897bb694979f580ff58b8b1d865783340eaff2d1ce738409ec1c62c1bd7f632cf0730a5634a1a2d91244b865302339c1861655e11b264aeaf2feefbf2d1222bb13c6bd6b2d2379d9a548f93de4d2a044928458eafa745021e0a69796bb40f17c1ca53b895c76b53924faa886a4a19f07b50eda5f316e5f3b5422e984c59928144c275d4ae5e78634e16c6dafcfc92bb302c7d5eef1456250b0b8a41f0cabb55dd114d6b0bcaf53ef1ee2185d2383df57a0f1bc21d31f5d3ae395bab6e77370ee83ffe8995e9bfbe2f90b3ff0578720e0584e969479d40327415835579d7b8885037c02a611292c6bbffde25e86c184cc7c7481e8856ce6a3cf7109a6c001e51a2289c5ee3633936578d4dc3de82c18ebb787bf2c475e8fa0393727cbdbcd36849ee0b7411fba6fd5cb8459e63aaf3fba7a4cd4a04b266d8f416f0586e2093ea9c210140a6e6cb72759ae1dee7c24497f68389fb8d154f927cc4ab59b9137652eaf9c7cb56f0cce6c58616646c6fee836b07ce738a965b1ea725d9960c47e61086be053f3e9c48c08ce945404b060d9e699ad962c910208dda42d665f8eacf9865a64d2612ea62e0e2c0a4c731b35ae87b04e45739c34f4c972ce433a2094b10a9601e6711b95a6a226a85f4e4ed0e0417dbc9d737cd7d3513a82943de94ff8e4c9e91838506283f4878e3f41488fec47198b4a262b55d3691d275c6154d2a2ce9ee6ab97087e0f33654b01450869797c993dfca76cd732677bf1856f43d040d68022055987588f64af357bea80491b4bc42341dd6f81631d30fc28e8c5d7e3312655b30d277f10ce76c2525279ad53157b1c2c78b412107fc5f974ac7946bdc33ee54d71f3fc261530d50f20813e4e6aadf39e67573d5dc93a45023edf297b56def6b14ec5e19ca10fbfd1b807f17fa983bec363cf495c708a581db1bba1a23730ce22d0f925d764b04be014d662c3a36ac58b015317c9cf5ca6464f2ecef15e1769f2c91922968532bda66e9aaa2a7f120a9301f563fd33db8e90c940984b0a297e0c595544b7f687476325a07dbaba255c8461e98f069eea2246cfa50f1c2ef8d4c54f5fd509a9cc839548d7c252e60bb9c165d05f30bd525f6b53a4c8afc8fc31026686bcd5a48172593941b3113cbed88e6cfb566f7a693bb63c9a89925c1f5df0a115b4893128866a81c1b + + 2. recv: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=a42ddd9ab2b171f945e1ac536cd2fc7e4c39d9f0fbb6172f3ec88020e8240033336f9d79ddad09391b41e5127c457abc2d59e59fb398cdd1cd5baed5ba16480c !option_static_remotekey + signature=05f85dd6f09a5004f11140b2da5b7c1e2debfd84232b04943b26a10da4f30856670e670e6618629f95d3b76f0167a9d906f92f2023884c8b24354b78be8b6fb8 option_static_remotekey + htlc_signature= + + 3. expect-send: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc + # per_commitment_secret 2=2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8 + next_per_commitment_point=03bca7c4ebe7eb7e8e40b8c2a7b4dde7f4d48404c9a62859d09fe2d00151af40ad + + 4. expect-send: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=0c10c223bc7db29d6a9bb054ecf2d72d26e2c73b9ebc653c13a965219f28e29f79e639f01f5082a4b155bbcb0a50acbd5ad9e5c1b4e62b369c57f4b85afa9164 + htlc_signature= + + # Optional reconnection testing. + 1. nothing + + # Ignore unknown odd messages + 1. recv: type=9999 + + # If tester did not receive node's revoke_and_ack: + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=1 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02037803a3228ec3a517835480ffac64c0557d9d75e0fe85861ab0be9eb224e6f8 option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + # - MUST re-send the `revoke_and_ack`. + 8. expect-send: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc + # per_commitment_secret 2=2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8 + next_per_commitment_point=03bca7c4ebe7eb7e8e40b8c2a7b4dde7f4d48404c9a62859d09fe2d00151af40ad + 9. expect-send: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=0c10c223bc7db29d6a9bb054ecf2d72d26e2c73b9ebc653c13a965219f28e29f79e639f01f5082a4b155bbcb0a50acbd5ad9e5c1b4e62b369c57f4b85afa9164 + htlc_signature= + + # If tester did receive node's revoke_and_ack, but not commitment_signed + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=1 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02037803a3228ec3a517835480ffac64c0557d9d75e0fe85861ab0be9eb224e6f8 option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + 8. expect-send: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=0c10c223bc7db29d6a9bb054ecf2d72d26e2c73b9ebc653c13a965219f28e29f79e639f01f5082a4b155bbcb0a50acbd5ad9e5c1b4e62b369c57f4b85afa9164 + htlc_signature= + + # If tester did receive node's commitment_signed + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=027eed8389cf8eb715d73111b73d94d2c2d04bf96dc43dfd5b0970d80b3617009d option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + + 5. recv: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 + # per_commitment_secret #2=c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a + next_per_commitment_point=02e1ea4f6d28dade887280214c359fc808066a64e750e3c81747dc3074833ff0ad + + # Optional reconnection testing. + 1. nothing + + # Ignore unknown odd messages + 1. recv: type=9999 + + # tester must have received node's commitment_signed + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_data_loss_protect + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=027eed8389cf8eb715d73111b73d94d2c2d04bf96dc43dfd5b0970d80b3617009d option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + + # Add a non-dust HTLC + 1. recv: type=update_add_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=0 + amount_msat=1000000 + # preimage=0000000000000000000000000000000000000000000000000000000000000000 + payment_hash=66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925 + cltv_expiry=200 + # hop_data[0] = 00000000000000000000000000000F4240000000C8000000000000000000000000 + onion_routing_packet=0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619b1153ae94698ea83a3298ab3c0ddd6b6fd853e4e5fbc5d4f3cb457bbb74a9b81d3b5bc9cf42d8617d1fe6966ffb66b8ec0eaa1188865957e26df123d11705395d339472bcc4920e428492f7822424eef8e6d903a768ec01959f3a1f2c1cd8725ba13329df3a932f641dee600dbb1a9f3bbe93a167410961f1777a7b48679d8a3041d57c0b8e795ed4884fbb33a2564d4cdafb528c7b63fc31cd2739e71d1d3b56f35ba7976a373b883eed8f1f263aedd540cce9b548e53e58c32ab604195f6004d8d92fe0a9a454229b9bc0795f3e4ccd54089075483afaa0ef3b32ee12cf321052f7b9e5ac1c28169e57d5628c3aee5c775d5fb33ba835fda195981b1e3a06792bdd0ecf85f8f6107fd830ca932e92c6713ea6d4d5129395f54aeabb54debccca130ad019a1f53a20c0c46dd8625ada068e2a13ea5373b60ecdf412728cc78192ae1a56bae26dfb450d2f6b4905e6bd9843fda7df63eb11fb77ce995b25d3076210eca527bb556b4ddc564fa4c6ccb43f1149163a4959ffe4178d653d35bdc052e4a46dd58b8f95fde83d114c4e35fd02e94a0dd2a9ae21594184808074a57d9de30c5105b53efe03aca192f8c518bc2b9e13211a9761c1948b31aa97f99da449968380005f96ff49a6e5fe833220a82f358eb94197584b2dfa5a1efee8918b5020f028748e5897bb694979f580ff58b8b1d865783340eaff2d1ce738409ec1c62c1bd7f632cf0730a5634a1a2d91244b865302339c1861655e11b264aeaf2feefbf2d1222bb13c6bd6b2d2379d9a548f93de4d2a044928458eafa745021e0a69796bb40f17c1ca53b895c76b53924faa886a4a19f07b50eda5f316e5f3b5422e984c59928144c275d4ae5e78634e16c6dafcfc92bb302c7d5eef1456250b0b8a41f0cabb55dd114d6b0bcaf53ef1ee2185d2383df57a0f1bc21d31f5d3ae395bab6e77370ee83ffe8995e9bfbe2f90b3ff0578720e0584e969479d40327415835579d7b8885037c02a611292c6bbffde25e86c184cc7c7481e8856ce6a3cf7109a6c001e51a2289c5ee3633936578d4dc3de82c18ebb787bf2c475e8fa0393727cbdbcd36849ee0b7411fba6fd5cb8459e63aaf3fba7a4cd4a04b266d8f416f0586e2093ea9c210140a6e6cb72759ae1dee7c24497f68389fb8d154f927cc4ab59b9137652eaf9c7cb56f0cce6c58616646c6fee836b07ce738a965b1ea725d9960c47e61086be053f3e9c48c08ce945404b060d9e699ad962c910208dda42d665f8eacf9865a64d2612ea62e0e2c0a4c731b35ae87b04e45739c34f4c972ce433a2094b10a9601e6711b95a6a226a85f4e4ed0e0417dbc9d737cd7d3513a82943de94ff8e4c9e91838506283f4878e3f41488fec47198b4a262b55d3691d275c6154d2a2ce9ee6ab97087e0f33654b01450869797c993dfca76cd732677bf1856f43d040d68022055987588f64af357bea80491b4bc42341dd6f81631d30fc28e8c5d7e3312655b30d277f10ce76c2525279ad53157b1c2c78b412107fc5f974ac7946bdc33ee54d71f3fc261530d50f20813e4e6aadf39e67573d5dc93a45023edf297b56def6b14ec5e19ca10fbfd1b807f17fa983bec363cf495c708a581db1bba1a23730ce22d0f925d764b04be014d662c3a36ac58b015317c9cf5ca6464f2ecef15e1769f2c91922968532bda66e9aaa2a7f120a9301f563fd33db8e90c940984b0a297e0c595544b7f687476325a07dbaba255c8461e98f069eea2246cfa50f1c2ef8d4c54f5fd509a9cc839548d7c252e60bb9c165d05f30bd525f6b53a4c8afc8fc31026686bcd5a48172593941b1450d92edf1300d7cfd2ffa175ab1c551817d67b9d095c976faaa23e598ba243 + + # Optional reconnection testing. + 1. nothing + + # Ignore unknown odd messages + 1. recv: type=9999 + + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=1 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=0288a618cb6027c3218a37cbe9e882379f17d87d03f6e99d0b60292478d2aded06 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=1 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02037803a3228ec3a517835480ffac64c0557d9d75e0fe85861ab0be9eb224e6f8 option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + 8. expect-send: type=funding_locked + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 + 9. recv: type=update_add_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=0 + amount_msat=1000000 + # preimage=0000000000000000000000000000000000000000000000000000000000000000 + payment_hash=66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925 + cltv_expiry=200 + # hop_data[0] = 00000000000000000000000000000F4240000000C8000000000000000000000000 + onion_routing_packet=0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619b1153ae94698ea83a3298ab3c0ddd6b6fd853e4e5fbc5d4f3cb457bbb74a9b81d3b5bc9cf42d8617d1fe6966ffb66b8ec0eaa1188865957e26df123d11705395d339472bcc4920e428492f7822424eef8e6d903a768ec01959f3a1f2c1cd8725ba13329df3a932f641dee600dbb1a9f3bbe93a167410961f1777a7b48679d8a3041d57c0b8e795ed4884fbb33a2564d4cdafb528c7b63fc31cd2739e71d1d3b56f35ba7976a373b883eed8f1f263aedd540cce9b548e53e58c32ab604195f6004d8d92fe0a9a454229b9bc0795f3e4ccd54089075483afaa0ef3b32ee12cf321052f7b9e5ac1c28169e57d5628c3aee5c775d5fb33ba835fda195981b1e3a06792bdd0ecf85f8f6107fd830ca932e92c6713ea6d4d5129395f54aeabb54debccca130ad019a1f53a20c0c46dd8625ada068e2a13ea5373b60ecdf412728cc78192ae1a56bae26dfb450d2f6b4905e6bd9843fda7df63eb11fb77ce995b25d3076210eca527bb556b4ddc564fa4c6ccb43f1149163a4959ffe4178d653d35bdc052e4a46dd58b8f95fde83d114c4e35fd02e94a0dd2a9ae21594184808074a57d9de30c5105b53efe03aca192f8c518bc2b9e13211a9761c1948b31aa97f99da449968380005f96ff49a6e5fe833220a82f358eb94197584b2dfa5a1efee8918b5020f028748e5897bb694979f580ff58b8b1d865783340eaff2d1ce738409ec1c62c1bd7f632cf0730a5634a1a2d91244b865302339c1861655e11b264aeaf2feefbf2d1222bb13c6bd6b2d2379d9a548f93de4d2a044928458eafa745021e0a69796bb40f17c1ca53b895c76b53924faa886a4a19f07b50eda5f316e5f3b5422e984c59928144c275d4ae5e78634e16c6dafcfc92bb302c7d5eef1456250b0b8a41f0cabb55dd114d6b0bcaf53ef1ee2185d2383df57a0f1bc21d31f5d3ae395bab6e77370ee83ffe8995e9bfbe2f90b3ff0578720e0584e969479d40327415835579d7b8885037c02a611292c6bbffde25e86c184cc7c7481e8856ce6a3cf7109a6c001e51a2289c5ee3633936578d4dc3de82c18ebb787bf2c475e8fa0393727cbdbcd36849ee0b7411fba6fd5cb8459e63aaf3fba7a4cd4a04b266d8f416f0586e2093ea9c210140a6e6cb72759ae1dee7c24497f68389fb8d154f927cc4ab59b9137652eaf9c7cb56f0cce6c58616646c6fee836b07ce738a965b1ea725d9960c47e61086be053f3e9c48c08ce945404b060d9e699ad962c910208dda42d665f8eacf9865a64d2612ea62e0e2c0a4c731b35ae87b04e45739c34f4c972ce433a2094b10a9601e6711b95a6a226a85f4e4ed0e0417dbc9d737cd7d3513a82943de94ff8e4c9e91838506283f4878e3f41488fec47198b4a262b55d3691d275c6154d2a2ce9ee6ab97087e0f33654b01450869797c993dfca76cd732677bf1856f43d040d68022055987588f64af357bea80491b4bc42341dd6f81631d30fc28e8c5d7e3312655b30d277f10ce76c2525279ad53157b1c2c78b412107fc5f974ac7946bdc33ee54d71f3fc261530d50f20813e4e6aadf39e67573d5dc93a45023edf297b56def6b14ec5e19ca10fbfd1b807f17fa983bec363cf495c708a581db1bba1a23730ce22d0f925d764b04be014d662c3a36ac58b015317c9cf5ca6464f2ecef15e1769f2c91922968532bda66e9aaa2a7f120a9301f563fd33db8e90c940984b0a297e0c595544b7f687476325a07dbaba255c8461e98f069eea2246cfa50f1c2ef8d4c54f5fd509a9cc839548d7c252e60bb9c165d05f30bd525f6b53a4c8afc8fc31026686bcd5a48172593941b1450d92edf1300d7cfd2ffa175ab1c551817d67b9d095c976faaa23e598ba243 + + 2. recv: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + # !option_static_remotekey: + ## remote_commitment + # input amount 999878sat, funding_wscript 522103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e652103e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a52ae, key 03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + # unsigned remote commitment tx: 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a98002e8030000000000002200204a7ee4c37da8a8ab48e53517c27173098a61f794d2adb84faf0c86ec0c18385ffc3c0f0000000000160014ded1a6b285067b547db1d27bc87d32b84ac949cc4dff0020 + ## Output 0: LOCAL HTLC 0 + # unsigned htlc tx for output 0: 0200000001d3617e206fcf3d62ccaf0328e6ef88b9936afde335552e720226447eb4afffcc000000000000000000013703000000000000220020c950c75b39235322de605f8d8ff7533edf8cfa4e5edd090425c326cfbf4d216700000000 + # wscript: 76a9143eb3762c8c276c6298a7aa4b6891873d3a4cacd88763ac6721037c6136c02af011b4f0f592d2dc7fc8b5b273b394ed8e6457130ad7c74dda0b4f7c8201208763a914b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc688527c21027f79127629a39c5b967ed0f02a27e50e388efd95fe1601a1b74e50ca0eee92fd52ae677502c800b175ac6868 + signature=31f6f0ec18b50e61b0c0dc8632d0fc8b7a22883e55c01220d1fd4ad83b752a1a52af1978649e6525334d0c07c739a7537c26d38eaf1d7dab4a7bceffac04f6dd !option_static_remotekey + htlc_signature=fca89064c648f4264bcc6c0f8c630d7fcc9ede23b0eec23658fc772079e7b46f2fbea7265b1057159ba7a44096ef341fc469790997adaeb31dd3b0cf0478dd80 !option_static_remotekey + # option_static_remotekey: + ## remote_commitment + # input amount 999878sat, funding_wscript 522103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e652103e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a52ae, key 03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + # unsigned remote commitment tx: 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a98002e8030000000000002200204a7ee4c37da8a8ab48e53517c27173098a61f794d2adb84faf0c86ec0c18385ffc3c0f0000000000160014e142ca9bfc2d56cd0adb82f8dc870424767389f74dff0020 + # Output 0: LOCAL HTLC 0 + # unsigned htlc tx for output 0: 0200000001a366eac6a4f4aad69c3b292d275f1122e34aa97d091ae808422ef4b6d7599c5f000000000000000000013703000000000000220020cdd8da56037931fe7395cbe19893316feb98077ee1acb1b62f31ef850201f29000000000 + # wscript: 76a9143eb3762c8c276c6298a7aa4b6891873d3a4cacd88763ac6721037c6136c02af011b4f0f592d2dc7fc8b5b273b394ed8e6457130ad7c74dda0b4f7c8201208763a914b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc688527c21027f79127629a39c5b967ed0f02a27e50e388efd95fe1601a1b74e50ca0eee92fd52ae677502c800b175ac6868 + signature=69de461fb50707921427c8b204a15188820e21f4711fb72548794ecd036ab8ae1e38461426174f856ec9339f4ad827db42f940f87f916d8e0634521479d1521a option_static_remotekey + htlc_signature=3b04f576ccd0c35ad3fae12434f65a9d04bfe5d185a8ddb3a7afe7fef5a2316842c2e7a201474aaa7272b47db216711986b89adadf93f2fffba7613692c10c7d option_static_remotekey + + 3. expect-send: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc + # per_commitment_secret 2=2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8 + next_per_commitment_point=03bca7c4ebe7eb7e8e40b8c2a7b4dde7f4d48404c9a62859d09fe2d00151af40ad + + 4. expect-send: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + # Note: because we only have to-self output, signatures don't change + # with option_static_remotekey + signature=e8653ec993ef47417e941088f1d41bfa5a51bbf1d49d0633389f5a0bf5960918148113a4a7fdd32f114dc945a7db774ed9756ca84bb0e6aa5c330612f294956a + htlc_signature=9c3c9fa3c396aae512aaf7eeed42c3c38b9c8507c6ef60173249118fa823d41f1d93d1fd20c255d242813699332cbd7728c49c72a34653cd84a3fddbe41320c3 + + # Optional reconnection testing. + 1. nothing + + # Ignore unknown odd messages + 1. recv: type=9999 + + # If tester did not receive node's revoke_and_ack: + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=1 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02037803a3228ec3a517835480ffac64c0557d9d75e0fe85861ab0be9eb224e6f8 option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + # - MUST re-send the `revoke_and_ack`. + 8. expect-send: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc + # per_commitment_secret 2=2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8 + next_per_commitment_point=03bca7c4ebe7eb7e8e40b8c2a7b4dde7f4d48404c9a62859d09fe2d00151af40ad + 9. expect-send: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=e8653ec993ef47417e941088f1d41bfa5a51bbf1d49d0633389f5a0bf5960918148113a4a7fdd32f114dc945a7db774ed9756ca84bb0e6aa5c330612f294956a + htlc_signature=9c3c9fa3c396aae512aaf7eeed42c3c38b9c8507c6ef60173249118fa823d41f1d93d1fd20c255d242813699332cbd7728c49c72a34653cd84a3fddbe41320c3 + + # If tester did receive node's revoke_and_ack, but not commitment_signed + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=1 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02037803a3228ec3a517835480ffac64c0557d9d75e0fe85861ab0be9eb224e6f8 option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + 8. expect-send: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=e8653ec993ef47417e941088f1d41bfa5a51bbf1d49d0633389f5a0bf5960918148113a4a7fdd32f114dc945a7db774ed9756ca84bb0e6aa5c330612f294956a + htlc_signature=9c3c9fa3c396aae512aaf7eeed42c3c38b9c8507c6ef60173249118fa823d41f1d93d1fd20c255d242813699332cbd7728c49c72a34653cd84a3fddbe41320c3 + + # If tester did receive node's commitment_signed + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=027eed8389cf8eb715d73111b73d94d2c2d04bf96dc43dfd5b0970d80b3617009d option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + + 5. recv: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 + # per_commitment_secret #2=c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a + next_per_commitment_point=02e1ea4f6d28dade887280214c359fc808066a64e750e3c81747dc3074833ff0ad + + # Optional reconnection testing. + 1. nothing + + # Ignore unknown odd messages + 1. recv: type=9999 + + # tester must have received node's commitment_signed + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_data_loss_protect + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=027eed8389cf8eb715d73111b73d94d2c2d04bf96dc43dfd5b0970d80b3617009d option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE diff --git a/tests/events/bolt2-03-htlc-fail.events b/tests/events/bolt2-03-htlc-fail.events new file mode 100644 index 000000000..d9a6fe5a1 --- /dev/null +++ b/tests/events/bolt2-03-htlc-fail.events @@ -0,0 +1,409 @@ +# Variations on HTLC failure. + +# BOLT #7: +# The origin node: +# - MAY create a `channel_update` to communicate the channel +# parameters to the channel peer, even though the channel has not +# yet been announced (i.e. the `announce_channel` bit was not set). + +# In fact, it makes sense to do this after each reconnect. +MAYBE_UPDATE=maybe-send: type=channel_update + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + # FIXME: Fill other expected fields here! + +include setup.incl + +1. block: $BLOCK_102 + +2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 +3. expect-send: type=init +4. recv: type=init globalfeatures= localfeatures=02000000000002 +5. recv: type=open_channel + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + temporary_channel_id=0000000000000000000000000000000000000000000000000000000000000000 + funding_satoshis=999878 + push_msat=0 + dust_limit_satoshis=546 + max_htlc_value_in_flight_msat=4294967295 + channel_reserve_satoshis=9998 + htlc_minimum_msat=0 + feerate_per_kw=253 + # node has to_self_delay=6; we use 5 to test differentiation + to_self_delay=5 + max_accepted_htlcs=483 + # funding_privkey=0000000000000000000000000000000000000000000000000000000000000020 + funding_pubkey=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 + # revocation_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000021 + revocation_basepoint=021697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5 + # payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000022 + payment_basepoint=031be68a5a028f2601d0e80d468c344ba331d611b96c358b6032e8b4da0547fc11 + # delayed_payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000023 + delayed_payment_basepoint=03605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479 + # htlc_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000024 + htlc_basepoint=02e0392cfa338aaf2f0b56c563e3e5e67a5d5fefe3388f85d90c899da20f0198f9 + # shachain seed=0000000000000000000000000000000000000000000000000000000000000000 + # first per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 + first_per_commitment_point=02037803a3228ec3a517835480ffac64c0557d9d75e0fe85861ab0be9eb224e6f8 + channel_flags=01 + +6. expect-send: type=accept_channel + temporary_channel_id=0000000000000000000000000000000000000000000000000000000000000000 + # funding_privkey=0000000000000000000000000000000000000000000000000000000000000010 + funding_pubkey=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + # revocation_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000011 + revocation_basepoint=03defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34 + # payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000012 + payment_basepoint=025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc + # delayed_payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000013 + delayed_payment_basepoint=022b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c + # htlc_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000014 + htlc_basepoint=024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97 + # shachain seed=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + # per_commitment_secret #0=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc + first_per_commitment_point=0288a618cb6027c3218a37cbe9e882379f17d87d03f6e99d0b60292478d2aded06 + # If these are different, the commitment tx will be different! + to_self_delay=6 + channel_reserve_satoshis=9998 + +7. recv: type=funding_created + temporary_channel_id=0000000000000000000000000000000000000000000000000000000000000000 + # Funding tx is 020000000001016b85f654d8186f4d5dd32a977b2cf8c4b01ff4634152acba16b654c1c85a83160100000000ffffffff01c6410f0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738202473044022047e9e6e798ba9adb6c84bdcd6230a96fb6de9dcca84d81103fb2bc08906cb884022027599b1e80289eaf238e9a00119a79a0ccceab7d83d54719e10bd0c3300a0d34012102d6a3c2d0cf7904ab6af54d7c959435a452b24a63194e1c4e7c337d3ebbb3017b00000000 + # txid=41085b995c1f591cfc3ae79ccde012bf0b37c7bde23d80a61c9732bdd6210b2f + funding_txid=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + funding_output_index=0 + # !option_static_remotekey: node's commitment tx is 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a980010f410f0000000000160014749af8703f0d1fd8890a553bd62e9caf15f7bad44cff0020 + signature=c0c95040f0c132b5773b05fcc59e4a394059db70e6767567f26cbceecc580bcf27da384471a5efdaabd04090dd1d5c3765e849e5fdfe556eabba1ebca806b02a !option_static_remotekey + # option_static_remotekey: node's commitment tx is 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a980010f410f0000000000160014e142ca9bfc2d56cd0adb82f8dc870424767389f74cff0020 + signature=02ce278a17c48e926f93d5134e8f7486e01112a7d06c2ed1b1b5034fb9ace8072d1485ee012440fc85b46cf671a802db4597d482ced68dbfa26ee07b899e936a option_static_remotekey + +8. expect-send: type=funding_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + # test's commitment tx is 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a980010f410f0000000000220020233d69d88092351875ce0b9fd5ea576b2307c539eaed7abdf97fbb26720f01ac4cff0020 + signature=0adfc07a0168630b2e216aa8068dc8aa353be4b622a32ea7629f6d92c37dddcb1f1d605e686d4f49435f415dd9d76174b96b33c7c3e0d5f4eb1d0a9953ad95a1 + +9. block: height=103 n=3 tx=020000000001016b85f654d8186f4d5dd32a977b2cf8c4b01ff4634152acba16b654c1c85a83160100000000ffffffff01c6410f0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738202473044022047e9e6e798ba9adb6c84bdcd6230a96fb6de9dcca84d81103fb2bc08906cb884022027599b1e80289eaf238e9a00119a79a0ccceab7d83d54719e10bd0c3300a0d34012102d6a3c2d0cf7904ab6af54d7c959435a452b24a63194e1c4e7c337d3ebbb3017b00000000 + +10. expect-send: type=funding_locked + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 + +11. recv: type=funding_locked + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + # per_commitment_secret #1 = dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3 + next_per_commitment_point=027eed8389cf8eb715d73111b73d94d2c2d04bf96dc43dfd5b0970d80b3617009d + +12. $MAYBE_UPDATE + + # Add a dust HTLC + 1. recv: type=update_add_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=0 + amount_msat=1000 + # preimage=0000000000000000000000000000000000000000000000000000000000000000 + payment_hash=66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925 + cltv_expiry=200 + # hop_data[0] = 00000000000000000000000000000003E8000000C8000000000000000000000000 + onion_routing_packet=0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619b1153ae94698ea83a3298ab3c0ddd9f755853e4e5fbc5d4f3cb457bbb74a9b81d3b5bc9cf42d8617d1fe6966ffb66b8ec0eaa1188865957e26df123d11705395d339472bcc4920e428492f7822424eef8e6d903a768ec01959f3a1f2c1cd8725ba13329df3a932f641dee600dbb1a9f3bbe93a167410961f1777a7b48679d8a3041d57c0b8e795ed4884fbb33a2564d4cdafb528c7b63fc31cd2739e71d1d3b56f35ba7976a373b883eed8f1f263aedd540cce9b548e53e58c32ab604195f6004d8d92fe0a9a454229b9bc0795f3e4ccd54089075483afaa0ef3b32ee12cf321052f7b9e5ac1c28169e57d5628c3aee5c775d5fb33ba835fda195981b1e3a06792bdd0ecf85f8f6107fd830ca932e92c6713ea6d4d5129395f54aeabb54debccca130ad019a1f53a20c0c46dd8625ada068e2a13ea5373b60ecdf412728cc78192ae1a56bae26dfb450d2f6b4905e6bd9843fda7df63eb11fb77ce995b25d3076210eca527bb556b4ddc564fa4c6ccb43f1149163a4959ffe4178d653d35bdc052e4a46dd58b8f95fde83d114c4e35fd02e94a0dd2a9ae21594184808074a57d9de30c5105b53efe03aca192f8c518bc2b9e13211a9761c1948b31aa97f99da449968380005f96ff49a6e5fe833220a82f358eb94197584b2dfa5a1efee8918b5020f028748e5897bb694979f580ff58b8b1d865783340eaff2d1ce738409ec1c62c1bd7f632cf0730a5634a1a2d91244b865302339c1861655e11b264aeaf2feefbf2d1222bb13c6bd6b2d2379d9a548f93de4d2a044928458eafa745021e0a69796bb40f17c1ca53b895c76b53924faa886a4a19f07b50eda5f316e5f3b5422e984c59928144c275d4ae5e78634e16c6dafcfc92bb302c7d5eef1456250b0b8a41f0cabb55dd114d6b0bcaf53ef1ee2185d2383df57a0f1bc21d31f5d3ae395bab6e77370ee83ffe8995e9bfbe2f90b3ff0578720e0584e969479d40327415835579d7b8885037c02a611292c6bbffde25e86c184cc7c7481e8856ce6a3cf7109a6c001e51a2289c5ee3633936578d4dc3de82c18ebb787bf2c475e8fa0393727cbdbcd36849ee0b7411fba6fd5cb8459e63aaf3fba7a4cd4a04b266d8f416f0586e2093ea9c210140a6e6cb72759ae1dee7c24497f68389fb8d154f927cc4ab59b9137652eaf9c7cb56f0cce6c58616646c6fee836b07ce738a965b1ea725d9960c47e61086be053f3e9c48c08ce945404b060d9e699ad962c910208dda42d665f8eacf9865a64d2612ea62e0e2c0a4c731b35ae87b04e45739c34f4c972ce433a2094b10a9601e6711b95a6a226a85f4e4ed0e0417dbc9d737cd7d3513a82943de94ff8e4c9e91838506283f4878e3f41488fec47198b4a262b55d3691d275c6154d2a2ce9ee6ab97087e0f33654b01450869797c993dfca76cd732677bf1856f43d040d68022055987588f64af357bea80491b4bc42341dd6f81631d30fc28e8c5d7e3312655b30d277f10ce76c2525279ad53157b1c2c78b412107fc5f974ac7946bdc33ee54d71f3fc261530d50f20813e4e6aadf39e67573d5dc93a45023edf297b56def6b14ec5e19ca10fbfd1b807f17fa983bec363cf495c708a581db1bba1a23730ce22d0f925d764b04be014d662c3a36ac58b015317c9cf5ca6464f2ecef15e1769f2c91922968532bda66e9aaa2a7f120a9301f563fd33db8e90c940984b0a297e0c595544b7f687476325a07dbaba255c8461e98f069eea2246cfa50f1c2ef8d4c54f5fd509a9cc839548d7c252e60bb9c165d05f30bd525f6b53a4c8afc8fc31026686bcd5a48172593941b3113cbed88e6cfb566f7a693bb63c9a89925c1f5df0a115b4893128866a81c1b + + 2. recv: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=a42ddd9ab2b171f945e1ac536cd2fc7e4c39d9f0fbb6172f3ec88020e8240033336f9d79ddad09391b41e5127c457abc2d59e59fb398cdd1cd5baed5ba16480c !option_static_remotekey + signature=05f85dd6f09a5004f11140b2da5b7c1e2debfd84232b04943b26a10da4f30856670e670e6618629f95d3b76f0167a9d906f92f2023884c8b24354b78be8b6fb8 option_static_remotekey + htlc_signature= + + 3. expect-send: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc + # per_commitment_secret 2=2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8 + next_per_commitment_point=03bca7c4ebe7eb7e8e40b8c2a7b4dde7f4d48404c9a62859d09fe2d00151af40ad + + 4. expect-send: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=0c10c223bc7db29d6a9bb054ecf2d72d26e2c73b9ebc653c13a965219f28e29f79e639f01f5082a4b155bbcb0a50acbd5ad9e5c1b4e62b369c57f4b85afa9164 + htlc_signature= + + 5. recv: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 + # per_commitment_secret #2=c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a + next_per_commitment_point=02e1ea4f6d28dade887280214c359fc808066a64e750e3c81747dc3074833ff0ad + + # Optional reconnection testing. + 1. nothing + + # tester must have received node's commitment_signed + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_data_loss_protect + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=027eed8389cf8eb715d73111b73d94d2c2d04bf96dc43dfd5b0970d80b3617009d option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + + # Add a non-dust HTLC + 1. recv: type=update_add_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=0 + amount_msat=1000000 + # preimage=0000000000000000000000000000000000000000000000000000000000000000 + payment_hash=66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925 + cltv_expiry=200 + # hop_data[0] = 00000000000000000000000000000F4240000000C8000000000000000000000000 + onion_routing_packet=0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619b1153ae94698ea83a3298ab3c0ddd6b6fd853e4e5fbc5d4f3cb457bbb74a9b81d3b5bc9cf42d8617d1fe6966ffb66b8ec0eaa1188865957e26df123d11705395d339472bcc4920e428492f7822424eef8e6d903a768ec01959f3a1f2c1cd8725ba13329df3a932f641dee600dbb1a9f3bbe93a167410961f1777a7b48679d8a3041d57c0b8e795ed4884fbb33a2564d4cdafb528c7b63fc31cd2739e71d1d3b56f35ba7976a373b883eed8f1f263aedd540cce9b548e53e58c32ab604195f6004d8d92fe0a9a454229b9bc0795f3e4ccd54089075483afaa0ef3b32ee12cf321052f7b9e5ac1c28169e57d5628c3aee5c775d5fb33ba835fda195981b1e3a06792bdd0ecf85f8f6107fd830ca932e92c6713ea6d4d5129395f54aeabb54debccca130ad019a1f53a20c0c46dd8625ada068e2a13ea5373b60ecdf412728cc78192ae1a56bae26dfb450d2f6b4905e6bd9843fda7df63eb11fb77ce995b25d3076210eca527bb556b4ddc564fa4c6ccb43f1149163a4959ffe4178d653d35bdc052e4a46dd58b8f95fde83d114c4e35fd02e94a0dd2a9ae21594184808074a57d9de30c5105b53efe03aca192f8c518bc2b9e13211a9761c1948b31aa97f99da449968380005f96ff49a6e5fe833220a82f358eb94197584b2dfa5a1efee8918b5020f028748e5897bb694979f580ff58b8b1d865783340eaff2d1ce738409ec1c62c1bd7f632cf0730a5634a1a2d91244b865302339c1861655e11b264aeaf2feefbf2d1222bb13c6bd6b2d2379d9a548f93de4d2a044928458eafa745021e0a69796bb40f17c1ca53b895c76b53924faa886a4a19f07b50eda5f316e5f3b5422e984c59928144c275d4ae5e78634e16c6dafcfc92bb302c7d5eef1456250b0b8a41f0cabb55dd114d6b0bcaf53ef1ee2185d2383df57a0f1bc21d31f5d3ae395bab6e77370ee83ffe8995e9bfbe2f90b3ff0578720e0584e969479d40327415835579d7b8885037c02a611292c6bbffde25e86c184cc7c7481e8856ce6a3cf7109a6c001e51a2289c5ee3633936578d4dc3de82c18ebb787bf2c475e8fa0393727cbdbcd36849ee0b7411fba6fd5cb8459e63aaf3fba7a4cd4a04b266d8f416f0586e2093ea9c210140a6e6cb72759ae1dee7c24497f68389fb8d154f927cc4ab59b9137652eaf9c7cb56f0cce6c58616646c6fee836b07ce738a965b1ea725d9960c47e61086be053f3e9c48c08ce945404b060d9e699ad962c910208dda42d665f8eacf9865a64d2612ea62e0e2c0a4c731b35ae87b04e45739c34f4c972ce433a2094b10a9601e6711b95a6a226a85f4e4ed0e0417dbc9d737cd7d3513a82943de94ff8e4c9e91838506283f4878e3f41488fec47198b4a262b55d3691d275c6154d2a2ce9ee6ab97087e0f33654b01450869797c993dfca76cd732677bf1856f43d040d68022055987588f64af357bea80491b4bc42341dd6f81631d30fc28e8c5d7e3312655b30d277f10ce76c2525279ad53157b1c2c78b412107fc5f974ac7946bdc33ee54d71f3fc261530d50f20813e4e6aadf39e67573d5dc93a45023edf297b56def6b14ec5e19ca10fbfd1b807f17fa983bec363cf495c708a581db1bba1a23730ce22d0f925d764b04be014d662c3a36ac58b015317c9cf5ca6464f2ecef15e1769f2c91922968532bda66e9aaa2a7f120a9301f563fd33db8e90c940984b0a297e0c595544b7f687476325a07dbaba255c8461e98f069eea2246cfa50f1c2ef8d4c54f5fd509a9cc839548d7c252e60bb9c165d05f30bd525f6b53a4c8afc8fc31026686bcd5a48172593941b1450d92edf1300d7cfd2ffa175ab1c551817d67b9d095c976faaa23e598ba243 + + 2. recv: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=31f6f0ec18b50e61b0c0dc8632d0fc8b7a22883e55c01220d1fd4ad83b752a1a52af1978649e6525334d0c07c739a7537c26d38eaf1d7dab4a7bceffac04f6dd !option_static_remotekey + htlc_signature=fca89064c648f4264bcc6c0f8c630d7fcc9ede23b0eec23658fc772079e7b46f2fbea7265b1057159ba7a44096ef341fc469790997adaeb31dd3b0cf0478dd80 !option_static_remotekey + signature=69de461fb50707921427c8b204a15188820e21f4711fb72548794ecd036ab8ae1e38461426174f856ec9339f4ad827db42f940f87f916d8e0634521479d1521a option_static_remotekey + htlc_signature=3b04f576ccd0c35ad3fae12434f65a9d04bfe5d185a8ddb3a7afe7fef5a2316842c2e7a201474aaa7272b47db216711986b89adadf93f2fffba7613692c10c7d option_static_remotekey + + 3. expect-send: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc + # per_commitment_secret 2=2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8 + next_per_commitment_point=03bca7c4ebe7eb7e8e40b8c2a7b4dde7f4d48404c9a62859d09fe2d00151af40ad + + 4. expect-send: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=e8653ec993ef47417e941088f1d41bfa5a51bbf1d49d0633389f5a0bf5960918148113a4a7fdd32f114dc945a7db774ed9756ca84bb0e6aa5c330612f294956a + htlc_signature=9c3c9fa3c396aae512aaf7eeed42c3c38b9c8507c6ef60173249118fa823d41f1d93d1fd20c255d242813699332cbd7728c49c72a34653cd84a3fddbe41320c3 + + 5. recv: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 + # per_commitment_secret #2=c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a + next_per_commitment_point=02e1ea4f6d28dade887280214c359fc808066a64e750e3c81747dc3074833ff0ad + + # Optional reconnection testing. + 1. nothing + + # tester must have received node's commitment_signed + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_data_loss_protect + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + my_current_per_commitment_point=027eed8389cf8eb715d73111b73d94d2c2d04bf96dc43dfd5b0970d80b3617009d option_data_loss_protect + 7. $MAYBE_UPDATE + +# Either way, it should reject HTLC, as it's not a known preimage. +13. expect-send: type=update_fail_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=0 + # FIXME: check that reason is correct! + + # Optional reconnection testing. + 1. nothing + + # Ignore unknown odd messages + 1. recv: type=9999 + + # tester must have received node's commitment_signed + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_data_loss_protect + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=027eed8389cf8eb715d73111b73d94d2c2d04bf96dc43dfd5b0970d80b3617009d option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + # Now it will re-transmit + 8. expect-send: type=update_fail_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=0 + +14. expect-send: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=2a09e2db7995e4c48feb6ae56bf1a61745250611bfa3cb78865d2cf6c651bc217e1ead697eeafb2bff832ac97f3aae00c24f9e1f57310036381c03b14a5b7a56 + htlc_signature= + + # Optional reconnection testing. + 1. nothing + + # Ignore unknown odd messages + 1. recv: type=9999 + + # tester has not received last commitment_signed + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_data_loss_protect + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=027eed8389cf8eb715d73111b73d94d2c2d04bf96dc43dfd5b0970d80b3617009d option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + # Now it will re-transmit + 8. expect-send: type=update_fail_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=0 + 9. expect-send: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=2a09e2db7995e4c48feb6ae56bf1a61745250611bfa3cb78865d2cf6c651bc217e1ead697eeafb2bff832ac97f3aae00c24f9e1f57310036381c03b14a5b7a56 + htlc_signature= + + # tester *has* received last commitment_signed + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_data_loss_protect + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=3 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02e1ea4f6d28dade887280214c359fc808066a64e750e3c81747dc3074833ff0ad option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + +15. recv: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3 + # per_commitment_secret #3=ba65d7b0ef55a3ba300d4e87af29868f394f8f138d78a7011669c79b37b936f4 + next_per_commitment_point=030f1b0e7b158de0d85a05ec050304dcf189c879a888e5ca1ce45e829d4b075d37 + + # Optional reconnection testing. + 1. nothing + + # Ignore unknown odd messages + 1. recv: type=9999 + + # tester must have received last commitment_signed + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=2 + your_last_per_commitment_secret=dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3 option_data_loss_protect + your_last_per_commitment_secret=dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=3 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02e1ea4f6d28dade887280214c359fc808066a64e750e3c81747dc3074833ff0ad option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + +16. recv: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=bd02908f18c3aa740a84b75912a231b9ad773f72ebe2bd0d8d353bef47302e7f08d02272b7077bc8101613695651a756d9339febe714ad5648ff511974c140e7 !option_static_remotekey + signature=f1147918abcc66b802756ed8980bf6432e334e1217a9a7aeb2442e95677e66953beb5c6fe468589481b7e0323b8e5560ea2e675462f8e28bbcad38b50a3ed1e0 option_static_remotekey + htlc_signature= + +17. expect-send: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964 + # per_commitment_secret #3=27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116 + next_per_commitment_point=02d8489d0db616cbdfc77d5eadd56c1bc8f136b8fb6b184167ff5cc7fceed71977 + + # Optional reconnection testing. + 1. nothing + + # Ignore unknown odd messages + 1. recv: type=9999 + + # tester *has not* received revoke_and_ack + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=3 + next_revocation_number=2 + your_last_per_commitment_secret=dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3 option_data_loss_protect + your_last_per_commitment_secret=dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=03bca7c4ebe7eb7e8e40b8c2a7b4dde7f4d48404c9a62859d09fe2d00151af40ad option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=3 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02e1ea4f6d28dade887280214c359fc808066a64e750e3c81747dc3074833ff0ad option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + + # tester *has* received revoke_and_ack + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=3 + next_revocation_number=2 + your_last_per_commitment_secret=dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3 option_data_loss_protect + your_last_per_commitment_secret=dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=03bca7c4ebe7eb7e8e40b8c2a7b4dde7f4d48404c9a62859d09fe2d00151af40ad option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=3 + next_revocation_number=2 + your_last_per_commitment_secret=c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964 option_data_loss_protect + your_last_per_commitment_secret=c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02e1ea4f6d28dade887280214c359fc808066a64e750e3c81747dc3074833ff0ad option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE diff --git a/tests/events/bolt2-04-htlc-fulfill.events b/tests/events/bolt2-04-htlc-fulfill.events new file mode 100644 index 000000000..689148743 --- /dev/null +++ b/tests/events/bolt2-04-htlc-fulfill.events @@ -0,0 +1,403 @@ +# Variations on HTLC success. + +# BOLT #7: +# The origin node: +# - MAY create a `channel_update` to communicate the channel +# parameters to the channel peer, even though the channel has not +# yet been announced (i.e. the `announce_channel` bit was not set). + +# In fact, it makes sense to do this after each reconnect. +MAYBE_UPDATE=maybe-send: type=channel_update + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + # FIXME: Fill other expected fields here! + +include setup.incl + +1. block: $BLOCK_102 + +# Make two invoices: one is dust, one is not. +2. invoice: amount=1000 preimage=0000000000000000000000000000000000000000000000000000000000001000 +3. invoice: amount=1000000 preimage=0000000000000000000000000000000000000000000000000000000001000000 + +4. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 +5. expect-send: type=init +6. recv: type=init globalfeatures= localfeatures=02000000000002 +7. recv: type=open_channel + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + temporary_channel_id=0000000000000000000000000000000000000000000000000000000000000000 + funding_satoshis=999878 + push_msat=0 + dust_limit_satoshis=546 + max_htlc_value_in_flight_msat=4294967295 + channel_reserve_satoshis=9998 + htlc_minimum_msat=0 + feerate_per_kw=253 + to_self_delay=5 + max_accepted_htlcs=483 + # funding_privkey=0000000000000000000000000000000000000000000000000000000000000020 + funding_pubkey=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 + # revocation_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000021 + revocation_basepoint=021697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5 + # payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000022 + payment_basepoint=031be68a5a028f2601d0e80d468c344ba331d611b96c358b6032e8b4da0547fc11 + # delayed_payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000023 + delayed_payment_basepoint=03605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479 + # htlc_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000024 + htlc_basepoint=02e0392cfa338aaf2f0b56c563e3e5e67a5d5fefe3388f85d90c899da20f0198f9 + # shachain seed=0000000000000000000000000000000000000000000000000000000000000000 + # first per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 + first_per_commitment_point=02037803a3228ec3a517835480ffac64c0557d9d75e0fe85861ab0be9eb224e6f8 + channel_flags=01 + +8. expect-send: type=accept_channel + temporary_channel_id=0000000000000000000000000000000000000000000000000000000000000000 + # funding_privkey=0000000000000000000000000000000000000000000000000000000000000010 + funding_pubkey=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + # revocation_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000011 + revocation_basepoint=03defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34 + # payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000012 + payment_basepoint=025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc + # delayed_payment_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000013 + delayed_payment_basepoint=022b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c + # htlc_basepoint_secret=0000000000000000000000000000000000000000000000000000000000000014 + htlc_basepoint=024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97 + # shachain seed=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + # per_commitment_secret #0=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc + first_per_commitment_point=0288a618cb6027c3218a37cbe9e882379f17d87d03f6e99d0b60292478d2aded06 + # If these are different, the commitment tx will be different! + to_self_delay=6 + channel_reserve_satoshis=9998 + +9. recv: type=funding_created + temporary_channel_id=0000000000000000000000000000000000000000000000000000000000000000 + # Funding tx is 020000000001016b85f654d8186f4d5dd32a977b2cf8c4b01ff4634152acba16b654c1c85a83160100000000ffffffff01c6410f0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738202473044022047e9e6e798ba9adb6c84bdcd6230a96fb6de9dcca84d81103fb2bc08906cb884022027599b1e80289eaf238e9a00119a79a0ccceab7d83d54719e10bd0c3300a0d34012102d6a3c2d0cf7904ab6af54d7c959435a452b24a63194e1c4e7c337d3ebbb3017b00000000 + # txid=41085b995c1f591cfc3ae79ccde012bf0b37c7bde23d80a61c9732bdd6210b2f + funding_txid=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + funding_output_index=0 + # !option_static_remotekey: node's commitment tx is 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a980010f410f0000000000160014749af8703f0d1fd8890a553bd62e9caf15f7bad44cff0020 + signature=c0c95040f0c132b5773b05fcc59e4a394059db70e6767567f26cbceecc580bcf27da384471a5efdaabd04090dd1d5c3765e849e5fdfe556eabba1ebca806b02a !option_static_remotekey + # option_static_remotekey: node's commitment tx is 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a980010f410f0000000000160014e142ca9bfc2d56cd0adb82f8dc870424767389f74cff0020 + signature=02ce278a17c48e926f93d5134e8f7486e01112a7d06c2ed1b1b5034fb9ace8072d1485ee012440fc85b46cf671a802db4597d482ced68dbfa26ee07b899e936a option_static_remotekey + +10. expect-send: type=funding_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + # test's commitment tx is 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a980010f410f0000000000220020233d69d88092351875ce0b9fd5ea576b2307c539eaed7abdf97fbb26720f01ac4cff0020 + signature=0adfc07a0168630b2e216aa8068dc8aa353be4b622a32ea7629f6d92c37dddcb1f1d605e686d4f49435f415dd9d76174b96b33c7c3e0d5f4eb1d0a9953ad95a1 + +11. block: height=103 n=3 tx=020000000001016b85f654d8186f4d5dd32a977b2cf8c4b01ff4634152acba16b654c1c85a83160100000000ffffffff01c6410f0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738202473044022047e9e6e798ba9adb6c84bdcd6230a96fb6de9dcca84d81103fb2bc08906cb884022027599b1e80289eaf238e9a00119a79a0ccceab7d83d54719e10bd0c3300a0d34012102d6a3c2d0cf7904ab6af54d7c959435a452b24a63194e1c4e7c337d3ebbb3017b00000000 + +12. expect-send: type=funding_locked + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 + +13. recv: type=funding_locked + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + # per_commitment_secret #1 = dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3 + next_per_commitment_point=027eed8389cf8eb715d73111b73d94d2c2d04bf96dc43dfd5b0970d80b3617009d + +14. $MAYBE_UPDATE + +# First invoice-paying HTLC +15. recv: type=update_add_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=0 + amount_msat=1000 + # preimage=0000000000000000000000000000000000000000000000000000000000001000 + payment_hash=0193d8ff39177fc604d8c0e60d5495222da10cd84d4ae6d12bf84ca923158b31 + cltv_expiry=200 + # hop_data[0] = 00000000000000000000000000000003E8000000C8000000000000000000000000 + onion_routing_packet=0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619b1153ae94698ea83a3298ab3c0ddd9f755853e4e5fbc5d4f3cb457bbb74a9b81d3b5bc9cf42d8617d1fe6966ffb66b8ec0eaa1188865957e26df123d11705395d339472bcc4920e428492f7822424eef8e6d903a768ec01959f3a1f2c1cd8725ba13329df3a932f641dee600dbb1a9f3bbe93a167410961f1777a7b48679d8a3041d57c0b8e795ed4884fbb33a2564d4cdafb528c7b63fc31cd2739e71d1d3b56f35ba7976a373b883eed8f1f263aedd540cce9b548e53e58c32ab604195f6004d8d92fe0a9a454229b9bc0795f3e4ccd54089075483afaa0ef3b32ee12cf321052f7b9e5ac1c28169e57d5628c3aee5c775d5fb33ba835fda195981b1e3a06792bdd0ecf85f8f6107fd830ca932e92c6713ea6d4d5129395f54aeabb54debccca130ad019a1f53a20c0c46dd8625ada068e2a13ea5373b60ecdf412728cc78192ae1a56bae26dfb450d2f6b4905e6bd9843fda7df63eb11fb77ce995b25d3076210eca527bb556b4ddc564fa4c6ccb43f1149163a4959ffe4178d653d35bdc052e4a46dd58b8f95fde83d114c4e35fd02e94a0dd2a9ae21594184808074a57d9de30c5105b53efe03aca192f8c518bc2b9e13211a9761c1948b31aa97f99da449968380005f96ff49a6e5fe833220a82f358eb94197584b2dfa5a1efee8918b5020f028748e5897bb694979f580ff58b8b1d865783340eaff2d1ce738409ec1c62c1bd7f632cf0730a5634a1a2d91244b865302339c1861655e11b264aeaf2feefbf2d1222bb13c6bd6b2d2379d9a548f93de4d2a044928458eafa745021e0a69796bb40f17c1ca53b895c76b53924faa886a4a19f07b50eda5f316e5f3b5422e984c59928144c275d4ae5e78634e16c6dafcfc92bb302c7d5eef1456250b0b8a41f0cabb55dd114d6b0bcaf53ef1ee2185d2383df57a0f1bc21d31f5d3ae395bab6e77370ee83ffe8995e9bfbe2f90b3ff0578720e0584e969479d40327415835579d7b8885037c02a611292c6bbffde25e86c184cc7c7481e8856ce6a3cf7109a6c001e51a2289c5ee3633936578d4dc3de82c18ebb787bf2c475e8fa0393727cbdbcd36849ee0b7411fba6fd5cb8459e63aaf3fba7a4cd4a04b266d8f416f0586e2093ea9c210140a6e6cb72759ae1dee7c24497f68389fb8d154f927cc4ab59b9137652eaf9c7cb56f0cce6c58616646c6fee836b07ce738a965b1ea725d9960c47e61086be053f3e9c48c08ce945404b060d9e699ad962c910208dda42d665f8eacf9865a64d2612ea62e0e2c0a4c731b35ae87b04e45739c34f4c972ce433a2094b10a9601e6711b95a6a226a85f4e4ed0e0417dbc9d737cd7d3513a82943de94ff8e4c9e91838506283f4878e3f41488fec47198b4a262b55d3691d275c6154d2a2ce9ee6ab97087e0f33654b01450869797c993dfca76cd732677bf1856f43d040d68022055987588f64af357bea80491b4bc42341dd6f81631d30fc28e8c5d7e3312655b30d277f10ce76c2525279ad53157b1c2c78b412107fc5f974ac7946bdc33ee54d71f3fc261530d50f20813e4e6aadf39e67573d5dc93a45023edf297b56def6b14ec5e19ca10fbfd1b807f17fa983bec363cf495c708a581db1bba1a23730ce22d0f925d764b04be014d662c3a36ac58b015317c9cf5ca6464f2ecef15e1769f2c91922968532bda66e9aaa2a7f120a9301f563fd33db8e90c940984b0a297e0c595544b7f687476325a07dbaba255c8461e98f069eea2246cfa50f1c2ef8d4c54f5fd509a9cc839548d7c252e60bb9c165d05f30bd525f6b53a4c8afc8fc31026686bcd5a48172593941ba2804c6057dd454fbb44ad5e52b3383b9bcfda3647eefe650ab93b99ee60c8da + +16. recv: type=update_add_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=1 + amount_msat=1000000 + # preimage=0000000000000000000000000000000000000000000000000000000001000000 + payment_hash=954a6575b642bdddd05409cf5973ba837f25b2e391950be91fa23334093d88f5 + cltv_expiry=200 + # hop_data[0] = 00000000000000000000000000000F4240000000C8000000000000000000000000 + onion_routing_packet=0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619b1153ae94698ea83a3298ab3c0ddd6b6fd853e4e5fbc5d4f3cb457bbb74a9b81d3b5bc9cf42d8617d1fe6966ffb66b8ec0eaa1188865957e26df123d11705395d339472bcc4920e428492f7822424eef8e6d903a768ec01959f3a1f2c1cd8725ba13329df3a932f641dee600dbb1a9f3bbe93a167410961f1777a7b48679d8a3041d57c0b8e795ed4884fbb33a2564d4cdafb528c7b63fc31cd2739e71d1d3b56f35ba7976a373b883eed8f1f263aedd540cce9b548e53e58c32ab604195f6004d8d92fe0a9a454229b9bc0795f3e4ccd54089075483afaa0ef3b32ee12cf321052f7b9e5ac1c28169e57d5628c3aee5c775d5fb33ba835fda195981b1e3a06792bdd0ecf85f8f6107fd830ca932e92c6713ea6d4d5129395f54aeabb54debccca130ad019a1f53a20c0c46dd8625ada068e2a13ea5373b60ecdf412728cc78192ae1a56bae26dfb450d2f6b4905e6bd9843fda7df63eb11fb77ce995b25d3076210eca527bb556b4ddc564fa4c6ccb43f1149163a4959ffe4178d653d35bdc052e4a46dd58b8f95fde83d114c4e35fd02e94a0dd2a9ae21594184808074a57d9de30c5105b53efe03aca192f8c518bc2b9e13211a9761c1948b31aa97f99da449968380005f96ff49a6e5fe833220a82f358eb94197584b2dfa5a1efee8918b5020f028748e5897bb694979f580ff58b8b1d865783340eaff2d1ce738409ec1c62c1bd7f632cf0730a5634a1a2d91244b865302339c1861655e11b264aeaf2feefbf2d1222bb13c6bd6b2d2379d9a548f93de4d2a044928458eafa745021e0a69796bb40f17c1ca53b895c76b53924faa886a4a19f07b50eda5f316e5f3b5422e984c59928144c275d4ae5e78634e16c6dafcfc92bb302c7d5eef1456250b0b8a41f0cabb55dd114d6b0bcaf53ef1ee2185d2383df57a0f1bc21d31f5d3ae395bab6e77370ee83ffe8995e9bfbe2f90b3ff0578720e0584e969479d40327415835579d7b8885037c02a611292c6bbffde25e86c184cc7c7481e8856ce6a3cf7109a6c001e51a2289c5ee3633936578d4dc3de82c18ebb787bf2c475e8fa0393727cbdbcd36849ee0b7411fba6fd5cb8459e63aaf3fba7a4cd4a04b266d8f416f0586e2093ea9c210140a6e6cb72759ae1dee7c24497f68389fb8d154f927cc4ab59b9137652eaf9c7cb56f0cce6c58616646c6fee836b07ce738a965b1ea725d9960c47e61086be053f3e9c48c08ce945404b060d9e699ad962c910208dda42d665f8eacf9865a64d2612ea62e0e2c0a4c731b35ae87b04e45739c34f4c972ce433a2094b10a9601e6711b95a6a226a85f4e4ed0e0417dbc9d737cd7d3513a82943de94ff8e4c9e91838506283f4878e3f41488fec47198b4a262b55d3691d275c6154d2a2ce9ee6ab97087e0f33654b01450869797c993dfca76cd732677bf1856f43d040d68022055987588f64af357bea80491b4bc42341dd6f81631d30fc28e8c5d7e3312655b30d277f10ce76c2525279ad53157b1c2c78b412107fc5f974ac7946bdc33ee54d71f3fc261530d50f20813e4e6aadf39e67573d5dc93a45023edf297b56def6b14ec5e19ca10fbfd1b807f17fa983bec363cf495c708a581db1bba1a23730ce22d0f925d764b04be014d662c3a36ac58b015317c9cf5ca6464f2ecef15e1769f2c91922968532bda66e9aaa2a7f120a9301f563fd33db8e90c940984b0a297e0c595544b7f687476325a07dbaba255c8461e98f069eea2246cfa50f1c2ef8d4c54f5fd509a9cc839548d7c252e60bb9c165d05f30bd525f6b53a4c8afc8fc31026686bcd5a48172593941b5be6403eef1373ff72577187afc526cac3c467f07dd00cc91886109c914781d7 + +17. recv: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + # !option_static_remotekey: + ## remote_commitment + # input amount 999878sat, funding_wscript 522103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e652103e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a52ae, key 03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + # unsigned remote commitment tx: 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a98002e80300000000000022002061a5a700a99098d0c53f5d58b0c4f041ab861467b4eb5841a9d80ba300daf8dafb3c0f0000000000160014ded1a6b285067b547db1d27bc87d32b84ac949cc4dff0020 + ## Output 0: LOCAL HTLC 1 + # unsigned htlc tx for output 0: 02000000014e7c13514515d6baba93a001522446dcb1fbcd73d759b647c9b835cb6c3800c2000000000000000000013703000000000000220020cdd8da56037931fe7395cbe19893316feb98077ee1acb1b62f31ef850201f29000000000 + # wscript: 76a9143eb3762c8c276c6298a7aa4b6891873d3a4cacd88763ac6721037c6136c02af011b4f0f592d2dc7fc8b5b273b394ed8e6457130ad7c74dda0b4f7c8201208763a9148139a4b000a75011a6f624005c9482c04160d94588527c21027f79127629a39c5b967ed0f02a27e50e388efd95fe1601a1b74e50ca0eee92fd52ae677502c800b175ac6868 + signature=bc5e1b465773cfe59478c5db35e9f9d27bf832436d0ed0c19833b5e7d444e9f26e3522883a110d71e715471727e3ea7703eba0e6e9855e8d59bc0bf93029bb29 !option_static_remotekey + htlc_signature=8ef6bc3d35a91a00cd1edb0a22e5ca7204b297d41cd7c4cdb1c4167d2d298d907e23b9dc75356ff2fee9ced4abc9fba796a90a2939df45080d12c7bbadbda8d8 !option_static_remotekey + # option_static_remotekey: + ## remote_commitment + # input amount 999878sat, funding_wscript 522103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e652103e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a52ae, key 03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + # unsigned remote commitment tx: 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a98002e80300000000000022002061a5a700a99098d0c53f5d58b0c4f041ab861467b4eb5841a9d80ba300daf8dafb3c0f0000000000160014e142ca9bfc2d56cd0adb82f8dc870424767389f74dff0020 + ## Output 0: LOCAL HTLC 1 + # unsigned htlc tx for output 0: 020000000162b2ce7a192e54c942c3abca50c0535cb60990f08480c7fbb02cf66d641d6f23000000000000000000013703000000000000220020cdd8da56037931fe7395cbe19893316feb98077ee1acb1b62f31ef850201f29000000000 + # wscript: 76a9143eb3762c8c276c6298a7aa4b6891873d3a4cacd88763ac6721037c6136c02af011b4f0f592d2dc7fc8b5b273b394ed8e6457130ad7c74dda0b4f7c8201208763a9148139a4b000a75011a6f624005c9482c04160d94588527c21027f79127629a39c5b967ed0f02a27e50e388efd95fe1601a1b74e50ca0eee92fd52ae677502c800b175ac6868 + signature=aafcc497d0b8e0c7e7593b6447408a058c321a81927153201a981ffa064ba12a761a6d34aedb35450208149f746167bc57026176536c548d7c8b40343bf65a36 option_static_remotekey + htlc_signature=eabc09f68e9195c2097060a5c8e4c1fa692afcf6c52c24ef4db775e299a028fb65445f591fc94f66172b94a2cabb1be4c0b95bd1cf14935cf6b423df4ae0288c option_static_remotekey + +18. expect-send: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc + # per_commitment_secret 2=2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8 + next_per_commitment_point=03bca7c4ebe7eb7e8e40b8c2a7b4dde7f4d48404c9a62859d09fe2d00151af40ad + +19. expect-send: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=64ce07df4f7d4e3e2a29ae6c78baf1d5087a5028f08f537eaed25a5fd1a1f73836d592ff80ba34bbd8f26a0fee17bc8a1fda64006fa4d28f9d52936e17d0abcb + htlc_signature=cfc5c03c510835df5d113b9da9ecdd1b73a602e5bd5a0703c9e53e863da3d8b1193c44913bdc856623f6a706a86256b4939115dec12a79c1f2585cfe7e91a472 + + # Optional reconnection testing. + 1. nothing + + # Ignore unknown odd messages + 1. recv: type=9999 + + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + + # If tester did not receive node's revoke_and_ack: + 1. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=1 + next_revocation_number=0 + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_data_loss_protect + your_last_per_commitment_secret=0000000000000000000000000000000000000000000000000000000000000000 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02037803a3228ec3a517835480ffac64c0557d9d75e0fe85861ab0be9eb224e6f8 option_data_loss_protect !option_static_remotekey + 2. $MAYBE_UPDATE + # - MUST re-send the `revoke_and_ack` and `commitment_signed` + 3. expect-send: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc + # per_commitment_secret 2=2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8 + next_per_commitment_point=03bca7c4ebe7eb7e8e40b8c2a7b4dde7f4d48404c9a62859d09fe2d00151af40ad + 4. expect-send: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=64ce07df4f7d4e3e2a29ae6c78baf1d5087a5028f08f537eaed25a5fd1a1f73836d592ff80ba34bbd8f26a0fee17bc8a1fda64006fa4d28f9d52936e17d0abcb + htlc_signature=cfc5c03c510835df5d113b9da9ecdd1b73a602e5bd5a0703c9e53e863da3d8b1193c44913bdc856623f6a706a86256b4939115dec12a79c1f2585cfe7e91a472 + + # If tester did receive node's revoke_and_ack, but not commitment_signed + 1. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=1 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02037803a3228ec3a517835480ffac64c0557d9d75e0fe85861ab0be9eb224e6f8 option_data_loss_protect !option_static_remotekey + 2. $MAYBE_UPDATE + # - MUST re-send `commitment_signed` + 3. expect-send: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=64ce07df4f7d4e3e2a29ae6c78baf1d5087a5028f08f537eaed25a5fd1a1f73836d592ff80ba34bbd8f26a0fee17bc8a1fda64006fa4d28f9d52936e17d0abcb + htlc_signature=cfc5c03c510835df5d113b9da9ecdd1b73a602e5bd5a0703c9e53e863da3d8b1193c44913bdc856623f6a706a86256b4939115dec12a79c1f2585cfe7e91a472 + + # If tester did receive node's commitment_signed + 1. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=027eed8389cf8eb715d73111b73d94d2c2d04bf96dc43dfd5b0970d80b3617009d option_data_loss_protect !option_static_remotekey + 2. $MAYBE_UPDATE + +20. recv: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 + # per_commitment_secret #2=c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a + next_per_commitment_point=02e1ea4f6d28dade887280214c359fc808066a64e750e3c81747dc3074833ff0ad + +# It should accept both of them, but could be in any order. +# (Could also do this in two separate commits, but I didn't add that). +21. Any order: + 1. expect-send: type=update_fulfill_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=0 + payment_preimage=0000000000000000000000000000000000000000000000000000000000001000 + 1. expect-send: type=update_fulfill_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=1 + payment_preimage=0000000000000000000000000000000000000000000000000000000001000000 + +# Separator: next is not part of Any order. +22. nothing + + # Optional reconnection testing. + 1. nothing + + # Ignore unknown odd messages + 1. recv: type=9999 + + # tester must have received node's commitment_signed + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_data_loss_protect + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + 6. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=027eed8389cf8eb715d73111b73d94d2c2d04bf96dc43dfd5b0970d80b3617009d option_data_loss_protect !option_static_remotekey + 7. $MAYBE_UPDATE + # Now it will re-transmit + 8. Any order: + 1. expect-send: type=update_fulfill_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=0 + payment_preimage=0000000000000000000000000000000000000000000000000000000000001000 + 1. expect-send: type=update_fulfill_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=1 + payment_preimage=0000000000000000000000000000000000000000000000000000000001000000 + +23. expect-send: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + # !option_static_remotekey: + # unsigned local commitment tx: 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a98002e903000000000000160014f546ff0865eeecfdef611a3298eca91e656e73b5263d0f00000000002200209d2eb597904551cd8f3b6ee050cef80002b976d5ccf447cefd6a6fc93966580c4eff0020 + signature=282eb3266f88fb48e3614562d9b5ea3d6ff9ffde640d29de194d208f3ea36b955e16a0706df24548f678efc47bab5d59c9baa87d2fcc357b65e4504763dd2956 !option_static_remotekey + + # option_static_remotekey: + # unsigned local commitment tx: 02000000012f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b08410000000000f436a98002e903000000000000160014f0f4189b8cf9f2db0ab8d3a3c009e1823a58842e263d0f00000000002200209d2eb597904551cd8f3b6ee050cef80002b976d5ccf447cefd6a6fc93966580c4eff0020 + signature=a1f6b847503848ae3f3c5b3422fe5a0f953efadacc776163c81927d241c83dac47b9852a5299adf433486f337221816187ca073227c9e82247c980800cc6f3d7 option_static_remotekey + htlc_signature= + + # Optional reconnection testing. + 1. nothing + + # Ignore unknown odd messages + 1. recv: type=9999 + + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_data_loss_protect + your_last_per_commitment_secret=02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=032405cbd0f41225d5f203fe4adac8401321a9e05767c5f8af97d51d2e81fbb206 option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + + # tester has not received last commitment_signed + 1. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=2 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=027eed8389cf8eb715d73111b73d94d2c2d04bf96dc43dfd5b0970d80b3617009d option_data_loss_protect !option_static_remotekey + 2. $MAYBE_UPDATE + # Now it will re-transmit + 3. Any order: + 1. expect-send: type=update_fulfill_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=0 + payment_preimage=0000000000000000000000000000000000000000000000000000000000001000 + 1. expect-send: type=update_fulfill_htlc + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + id=1 + payment_preimage=0000000000000000000000000000000000000000000000000000000001000000 + 4. expect-send: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=282eb3266f88fb48e3614562d9b5ea3d6ff9ffde640d29de194d208f3ea36b955e16a0706df24548f678efc47bab5d59c9baa87d2fcc357b65e4504763dd2956 !option_static_remotekey + signature=a1f6b847503848ae3f3c5b3422fe5a0f953efadacc776163c81927d241c83dac47b9852a5299adf433486f337221816187ca073227c9e82247c980800cc6f3d7 option_static_remotekey + htlc_signature= + + # tester *has* received last commitment_signed + 1. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=3 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02e1ea4f6d28dade887280214c359fc808066a64e750e3c81747dc3074833ff0ad option_data_loss_protect !option_static_remotekey + 2. $MAYBE_UPDATE + +24. recv: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3 + # per_commitment_secret #3=ba65d7b0ef55a3ba300d4e87af29868f394f8f138d78a7011669c79b37b936f4 + next_per_commitment_point=030f1b0e7b158de0d85a05ec050304dcf189c879a888e5ca1ce45e829d4b075d37 + +25. recv: type=commitment_signed + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + signature=85aebf2874c464db7eac10e0bad98b491c9ac943eae263bb4396d4e5feded12f1284e26196397313be31f4e83334eb5a6641cbec158e0fbfb22c4c488b3a28fd !option_static_remotekey + signature=b3aebb9a3b29967c6b1b667f0c167e0a6df0ca5b0196f6e8568a7da218e721c459f19525c4ec5cfdb6e2113e717ad6dd689aa38cde81f09d3614de01e72f1221 option_static_remotekey + htlc_signature= + +26. expect-send: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964 + # per_commitment_secret #3=27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116 + next_per_commitment_point=02d8489d0db616cbdfc77d5eadd56c1bc8f136b8fb6b184167ff5cc7fceed71977 + + # Optional reconnection testing. + 1. nothing + + # Ignore unknown odd messages + 1. recv: type=9999 + + 1. disconnect: + 2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000002 + 3. expect-send: type=init + 4. recv: type=init globalfeatures= localfeatures=02 + 5. expect-send: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=3 + next_revocation_number=2 + your_last_per_commitment_secret=dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3 option_data_loss_protect + your_last_per_commitment_secret=dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=03bca7c4ebe7eb7e8e40b8c2a7b4dde7f4d48404c9a62859d09fe2d00151af40ad option_data_loss_protect !option_static_remotekey + my_current_per_commitment_point=absent option_static_remotekey + + # tester *has not* received revoke_and_ack + 1. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=3 + next_revocation_number=1 + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_data_loss_protect + your_last_per_commitment_secret=7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02e1ea4f6d28dade887280214c359fc808066a64e750e3c81747dc3074833ff0ad option_data_loss_protect !option_static_remotekey + 2. $MAYBE_UPDATE + 3. expect-send: type=revoke_and_ack + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + per_commitment_secret=c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964 + # per_commitment_secret #3=27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116 + next_per_commitment_point=02d8489d0db616cbdfc77d5eadd56c1bc8f136b8fb6b184167ff5cc7fceed71977 + + # tester *has* received revoke_and_ack + 1. recv: type=channel_reestablish + channel_id=2f0b21d6bd32971ca6803de2bdc7370bbf12e0cd9ce73afc1c591f5c995b0841 + next_commitment_number=3 + next_revocation_number=2 + your_last_per_commitment_secret=c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964 option_data_loss_protect + your_last_per_commitment_secret=c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964 option_static_remotekey !option_data_loss_protect + my_current_per_commitment_point=02e1ea4f6d28dade887280214c359fc808066a64e750e3c81747dc3074833ff0ad option_data_loss_protect !option_static_remotekey + 2. $MAYBE_UPDATE diff --git a/tests/events/bolt7-01-channel_announcement-success.events b/tests/events/bolt7-01-channel_announcement-success.events new file mode 100644 index 000000000..b48e64c8a --- /dev/null +++ b/tests/events/bolt7-01-channel_announcement-success.events @@ -0,0 +1,110 @@ +# Simple gossip tests. + +include setup.incl + +1. block: $BLOCK_102 + +2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000003 +3. expect-send: type=init +4. recv: type=init localfeatures= globalfeatures= + +# Funding tx spending 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b/1, feerate 253 to bitcoin privkeys 0000000000000000000000000000000000000000000000000000000000000010 and 0000000000000000000000000000000000000000000000000000000000000020 +# txid 189c40b0728f382fe91c87270926584e48e0af3a6789f37454afee6c7560311d +5. block: height=103 n=6 tx=020000000001016b85f654d8186f4d5dd32a977b2cf8c4b01ff4634152acba16b654c1c85a83160100000000ffffffff01c5410f0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d8187117382024730440220798d96d5a057b5b7797988a855217f41af05ece3ba8278366e2f69763c72e785022065d5dd7eeddc0766ddf65557c92b9c52c301f23f94d2cf681860d32153e6ae1e012102d6a3c2d0cf7904ab6af54d7c959435a452b24a63194e1c4e7c337d3ebbb3017b00000000 + +6. recv: type=channel_announcement + node_signature_1=63023be1b5b1f9fbb26fde890032bf4098fba6a78be75a8dd9deae332f6d20ec634806cc3477c41ca565c45089a8331beb3912fb896188b117d525ee17c85f63 + node_signature_2=7f2c0664c6205e3c9626b4b7618d18235c059f13579a41dd79ae99e1234d5e8709d295e77c3846b37c44edc7fc4bd1ab07b605c0d216973b6bb4d9dead54b98e + bitcoin_signature_1=083ccfe5a766dfe236446ddf52a4f89da5d3f3acc06851f2b0821223a069be02005f5cae7747451b8ae53709723c50fef2c7861c1b8b6bba1043e5bde56dbc39 + bitcoin_signature_2=157a587d3495da5b953ba4a9f3a6ad8479a114e4bacbf4262dc257dd86f10db949e6e34e12ef95ead4ba5a9e38b86cd530920b7054914f1ee61ed4261783aa12 + features= + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + node_id_1=02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 + node_id_2=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 + bitcoin_key_1=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + bitcoin_key_2=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 + +# New peer connects, asking for initial_routing_sync. We *won't* relay channel_announcement, as there is no channel_update. +7. connect: privkey=0000000000000000000000000000000000000000000000000000000000000005 +8. expect-send: type=init +9. recv: type=init localfeatures=08 globalfeatures= +10. must-not-send: type=channel_announcement +11. disconnect: + +12. recv: type=channel_update + signature=76df7e70c63cc2b63ef1c062b99c6d934a80ef2fd4dae9e1d86d277f47674af3255a97fa52ade7f129263f591ed784996eba6383135896cc117a438c80293282 + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + timestamp=1565587763 + message_flags=0 + channel_flags=0 + cltv_expiry_delta=144 + htlc_minimum_msat=0 + fee_base_msat=1000 + fee_proportional_millionths=10 + +# Now we'll relay to a new peer. +13. connect: privkey=0000000000000000000000000000000000000000000000000000000000000005 +14. expect-send: type=init +15. recv: type=init localfeatures=08 globalfeatures= +16. expect-send: type=channel_announcement + node_signature_1=63023be1b5b1f9fbb26fde890032bf4098fba6a78be75a8dd9deae332f6d20ec634806cc3477c41ca565c45089a8331beb3912fb896188b117d525ee17c85f63 + node_signature_2=7f2c0664c6205e3c9626b4b7618d18235c059f13579a41dd79ae99e1234d5e8709d295e77c3846b37c44edc7fc4bd1ab07b605c0d216973b6bb4d9dead54b98e + bitcoin_signature_1=083ccfe5a766dfe236446ddf52a4f89da5d3f3acc06851f2b0821223a069be02005f5cae7747451b8ae53709723c50fef2c7861c1b8b6bba1043e5bde56dbc39 + bitcoin_signature_2=157a587d3495da5b953ba4a9f3a6ad8479a114e4bacbf4262dc257dd86f10db949e6e34e12ef95ead4ba5a9e38b86cd530920b7054914f1ee61ed4261783aa12 + features= + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + node_id_1=02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 + node_id_2=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 + bitcoin_key_1=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + bitcoin_key_2=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 +17. expect-send: type=channel_update + signature=76df7e70c63cc2b63ef1c062b99c6d934a80ef2fd4dae9e1d86d277f47674af3255a97fa52ade7f129263f591ed784996eba6383135896cc117a438c80293282 + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + timestamp=1565587763 + message_flags=0 + channel_flags=0 + cltv_expiry_delta=144 + htlc_minimum_msat=0 + fee_base_msat=1000 + fee_proportional_millionths=10 + +# And it will relay this, too. +18. recv: conn=0000000000000000000000000000000000000000000000000000000000000003 type=channel_update + signature=0b20265c60b98d6150097ea2ed73a0df4c870ed13defde348c799dd418671ca814837b7b46733d3f28f63b4f36768b44f6ec8dc52fbb08103e27c85ab1188c60 + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + timestamp=1565587763 + message_flags=1 + channel_flags=1 + cltv_expiry_delta=48 + htlc_minimum_msat=0 + fee_base_msat=100 + fee_proportional_millionths=11 + htlc_maximum_msat=100000 +19. expect-send: type=channel_update + signature=0b20265c60b98d6150097ea2ed73a0df4c870ed13defde348c799dd418671ca814837b7b46733d3f28f63b4f36768b44f6ec8dc52fbb08103e27c85ab1188c60 + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + timestamp=1565587763 + message_flags=1 + channel_flags=1 + cltv_expiry_delta=48 + htlc_minimum_msat=0 + fee_base_msat=100 + fee_proportional_millionths=11 + htlc_maximum_msat=100000 +20. disconnect: + +# Now, if channel closes, it won't be relayed. + +21. block: height=109 n=1 tx=020000000001011d3160756ceeaf5474f389673aafe0484e58260927871ce92f388f72b0409c180000000000ffffffff010e410f00000000001600141b42e1fc7b1cd93a469fa67ed5eabf36ce354dd60400483045022100d93a21312af5b9a46041d2189e5b72f593fc865d920f705d76a25a728de5790302207995cc2dd45ff20c96ccea8b117be41581da8b84466dabfeea728ed858a3a7fd0147304402206d9f5e3b2b2540002ffc37815cef3fbc4ba7646a7bca1aa7605941edd735dee802205130da104d584df6b59c18704c94cd4edd032aed7e0c3044dc8815183552f2dd0147522103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e652103e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a52ae00000000 + +22. connect: privkey=0000000000000000000000000000000000000000000000000000000000000005 +23. expect-send: type=init +24. recv: type=init localfeatures=08 globalfeatures= +25. must-not-send: type=channel_announcement +26. must-not-send: type=channel_update diff --git a/tests/events/bolt7-02-channel_announcement-failures.events b/tests/events/bolt7-02-channel_announcement-failures.events new file mode 100644 index 000000000..0fc8a12fa --- /dev/null +++ b/tests/events/bolt7-02-channel_announcement-failures.events @@ -0,0 +1,207 @@ +# Tests for malformed/bad channel_announcement +include setup.incl + +1. block: $BLOCK_102 + +2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000003 +3. expect-send: type=init +4. recv: type=init localfeatures= globalfeatures= + +# Funding tx spending 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b/1, feerate 253 to bitcoin privkeys 0000000000000000000000000000000000000000000000000000000000000010 and 0000000000000000000000000000000000000000000000000000000000000020 +# txid 189c40b0728f382fe91c87270926584e48e0af3a6789f37454afee6c7560311d +5. block: height=103 n=1 tx=020000000001016b85f654d8186f4d5dd32a977b2cf8c4b01ff4634152acba16b654c1c85a83160100000000ffffffff01c5410f0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d8187117382024730440220798d96d5a057b5b7797988a855217f41af05ece3ba8278366e2f69763c72e785022065d5dd7eeddc0766ddf65557c92b9c52c301f23f94d2cf681860d32153e6ae1e012102d6a3c2d0cf7904ab6af54d7c959435a452b24a63194e1c4e7c337d3ebbb3017b00000000 + + # Invalid `channel_announcement`: short_channel_id too young. + # It's allowed (even encouraged!) to cache this, so we separate this + # from the other tests. + 1. recv: type=channel_announcement + node_signature_1=63023be1b5b1f9fbb26fde890032bf4098fba6a78be75a8dd9deae332f6d20ec634806cc3477c41ca565c45089a8331beb3912fb896188b117d525ee17c85f63 + node_signature_2=7f2c0664c6205e3c9626b4b7618d18235c059f13579a41dd79ae99e1234d5e8709d295e77c3846b37c44edc7fc4bd1ab07b605c0d216973b6bb4d9dead54b98e + bitcoin_signature_1=083ccfe5a766dfe236446ddf52a4f89da5d3f3acc06851f2b0821223a069be02005f5cae7747451b8ae53709723c50fef2c7861c1b8b6bba1043e5bde56dbc39 + bitcoin_signature_2=157a587d3495da5b953ba4a9f3a6ad8479a114e4bacbf4262dc257dd86f10db949e6e34e12ef95ead4ba5a9e38b86cd530920b7054914f1ee61ed4261783aa12 + features= + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + node_id_1=02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 + node_id_2=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 + bitcoin_key_1=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + bitcoin_key_2=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 + + # Invalid `channel_announcement`: short_channel_id *still* too young. + 1. block: height=104 n=4 + 2. recv: type=channel_announcement + node_signature_1=63023be1b5b1f9fbb26fde890032bf4098fba6a78be75a8dd9deae332f6d20ec634806cc3477c41ca565c45089a8331beb3912fb896188b117d525ee17c85f63 + node_signature_2=7f2c0664c6205e3c9626b4b7618d18235c059f13579a41dd79ae99e1234d5e8709d295e77c3846b37c44edc7fc4bd1ab07b605c0d216973b6bb4d9dead54b98e + bitcoin_signature_1=083ccfe5a766dfe236446ddf52a4f89da5d3f3acc06851f2b0821223a069be02005f5cae7747451b8ae53709723c50fef2c7861c1b8b6bba1043e5bde56dbc39 + bitcoin_signature_2=157a587d3495da5b953ba4a9f3a6ad8479a114e4bacbf4262dc257dd86f10db949e6e34e12ef95ead4ba5a9e38b86cd530920b7054914f1ee61ed4261783aa12 + features= + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + node_id_1=02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 + node_id_2=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 + bitcoin_key_1=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + bitcoin_key_2=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 + + # This makes announcement otherwise acceptable. + 1. block: height=104 n=5 + + # Invalid `channel_announcement`: bad node_signature_1. + 1. recv: type=channel_announcement + node_signature_1=63023be1b5b1f9fbb26fde890032bf4098fba6a78be75a8dd9deae332f6d20ec634806cc3477c41ca565c45089a8331beb3912fb896188b117d525ee17c85f62 + node_signature_2=7f2c0664c6205e3c9626b4b7618d18235c059f13579a41dd79ae99e1234d5e8709d295e77c3846b37c44edc7fc4bd1ab07b605c0d216973b6bb4d9dead54b98e + bitcoin_signature_1=083ccfe5a766dfe236446ddf52a4f89da5d3f3acc06851f2b0821223a069be02005f5cae7747451b8ae53709723c50fef2c7861c1b8b6bba1043e5bde56dbc39 + bitcoin_signature_2=157a587d3495da5b953ba4a9f3a6ad8479a114e4bacbf4262dc257dd86f10db949e6e34e12ef95ead4ba5a9e38b86cd530920b7054914f1ee61ed4261783aa12 + features= + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + node_id_1=02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 + node_id_2=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 + bitcoin_key_1=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + bitcoin_key_2=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 + 2. expect-error: + + # Invalid `channel_announcement`: bad node_signature_2. + 1. recv: type=channel_announcement + node_signature_1=63023be1b5b1f9fbb26fde890032bf4098fba6a78be75a8dd9deae332f6d20ec634806cc3477c41ca565c45089a8331beb3912fb896188b117d525ee17c85f63 + node_signature_2=7f2c0664c6205e3c9626b4b7618d18235c059f13579a41dd79ae99e1234d5e8709d295e77c3846b37c44edc7fc4bd1ab07b605c0d216973b6bb4d9dead54b98f + bitcoin_signature_1=083ccfe5a766dfe236446ddf52a4f89da5d3f3acc06851f2b0821223a069be02005f5cae7747451b8ae53709723c50fef2c7861c1b8b6bba1043e5bde56dbc39 + bitcoin_signature_2=157a587d3495da5b953ba4a9f3a6ad8479a114e4bacbf4262dc257dd86f10db949e6e34e12ef95ead4ba5a9e38b86cd530920b7054914f1ee61ed4261783aa12 + features= + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + node_id_1=02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 + node_id_2=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 + bitcoin_key_1=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + bitcoin_key_2=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 + 2. expect-error: + + # Invalid `channel_announcement`: bad bitcoin_signature_1. + 1. recv: type=channel_announcement + node_signature_1=63023be1b5b1f9fbb26fde890032bf4098fba6a78be75a8dd9deae332f6d20ec634806cc3477c41ca565c45089a8331beb3912fb896188b117d525ee17c85f63 + node_signature_2=7f2c0664c6205e3c9626b4b7618d18235c059f13579a41dd79ae99e1234d5e8709d295e77c3846b37c44edc7fc4bd1ab07b605c0d216973b6bb4d9dead54b98e + bitcoin_signature_1=083ccfe5a766dfe236446ddf52a4f89da5d3f3acc06851f2b0821223a069be02005f5cae7747451b8ae53709723c50fef2c7861c1b8b6bba1043e5bde56dbc38 + bitcoin_signature_2=157a587d3495da5b953ba4a9f3a6ad8479a114e4bacbf4262dc257dd86f10db949e6e34e12ef95ead4ba5a9e38b86cd530920b7054914f1ee61ed4261783aa12 + features= + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + node_id_1=02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 + node_id_2=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 + bitcoin_key_1=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + bitcoin_key_2=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 + 2. expect-error: + + # Invalid `channel_announcement`: bad bitcoin_signature_2. + 1. recv: type=channel_announcement + node_signature_1=63023be1b5b1f9fbb26fde890032bf4098fba6a78be75a8dd9deae332f6d20ec634806cc3477c41ca565c45089a8331beb3912fb896188b117d525ee17c85f63 + node_signature_2=7f2c0664c6205e3c9626b4b7618d18235c059f13579a41dd79ae99e1234d5e8709d295e77c3846b37c44edc7fc4bd1ab07b605c0d216973b6bb4d9dead54b98e + bitcoin_signature_1=083ccfe5a766dfe236446ddf52a4f89da5d3f3acc06851f2b0821223a069be02005f5cae7747451b8ae53709723c50fef2c7861c1b8b6bba1043e5bde56dbc39 + bitcoin_signature_2=157a587d3495da5b953ba4a9f3a6ad8479a114e4bacbf4262dc257dd86f10db949e6e34e12ef95ead4ba5a9e38b86cd530920b7054914f1ee61ed4261783aa13 + features= + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + node_id_1=02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 + node_id_2=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 + bitcoin_key_1=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + bitcoin_key_2=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 + 2. expect-error: + + # Ignored `channel_announcement`: bad chain_hash + 1. recv: type=channel_announcement + node_signature_1=63023be1b5b1f9fbb26fde890032bf4098fba6a78be75a8dd9deae332f6d20ec634806cc3477c41ca565c45089a8331beb3912fb896188b117d525ee17c85f63 + node_signature_2=7f2c0664c6205e3c9626b4b7618d18235c059f13579a41dd79ae99e1234d5e8709d295e77c3846b37c44edc7fc4bd1ab07b605c0d216973b6bb4d9dead54b98e + bitcoin_signature_1=083ccfe5a766dfe236446ddf52a4f89da5d3f3acc06851f2b0821223a069be02005f5cae7747451b8ae53709723c50fef2c7861c1b8b6bba1043e5bde56dbc39 + bitcoin_signature_2=157a587d3495da5b953ba4a9f3a6ad8479a114e4bacbf4262dc257dd86f10db949e6e34e12ef95ead4ba5a9e38b86cd530920b7054914f1ee61ed4261783aa12 + features= + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf1889100 + short_channel_id=103x1x0 + node_id_1=02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 + node_id_2=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 + bitcoin_key_1=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + bitcoin_key_2=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 + + # Invalid `channel_announcement`: short_channel_id DNE + 1. recv: type=channel_announcement + node_signature_1=69d878cc06a2444a92244534aa2a106b2a8270299f20d15a693d2416fa60fb8535342929dfb17fcfcd4f800692d16994861037333a5f9503b3eaf1091acd18b4 + node_signature_2=dc678146f6f55db9d0751e24a045c1ce080aa973c1af9fbec7e2f088bb4eef322b746bb9cfcd3fddbf3b27f0b55517bc3f7e32d25652f51b7f1f7ca86d439b3b + bitcoin_signature_1=d0dca329a8705c92b7aa18f5d42731c31d17a0a0cd104c8e012c9c1f763f4f9857eba89b41264669c64be7316e38cd6c62a23bddb9db25773f28f421220339e4 + bitcoin_signature_2=f8cc9ac5c9147c3077b60f7768403a3f251d421672de0867e6c0314074679d373e9038be8253ae3668586e7cedc50f347725c2296274b7e8e9e26efee9374513 + features= + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x5x0 + node_id_1=02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 + node_id_2=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 + bitcoin_key_1=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + bitcoin_key_2=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 + + # Invalid `channel_announcement`: short_channel_id output DNE + 1. recv: type=channel_announcement + node_signature_1=ff3d3d3cf42b2a967b51407d0097fb5bb5035117726ddc16de9758cc1d11d87e65e468e5554b8d69ee2cd3ece701c75417f9a70c7dbd4139732aff0daba31ce4 + node_signature_2=5f709cca17429766bc7057c37d24b3820cc8541ae347b157ca693902b94729d6221000c776011cf427fdf7fff870262cadb4ed91fd44ee1fd7b2e5323d74ba17 + bitcoin_signature_1=0ab5cc881ac52e0e3644831c0a0da7a18c94a2cc51e09b637ba6cff3bedfba8146be0d666a6b82f374bedc682a75491303dd286773b68d97f523df3169cf16b2 + bitcoin_signature_2=9990fd49c489b880bf305fc56946356557c78cb306e915706b4ee02d8eec60497a322018f0e7b1896996860e304a82b3f27ea24038e63c05eb0e8fa1699dabb8 + features= + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x1 + node_id_1=02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 + node_id_2=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 + bitcoin_key_1=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + bitcoin_key_2=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 + + # Invalid `channel_announcement`: short_channel_id tx does not match + # (second bitcoin privkey is ...021 instead of ...020) + 1. recv: type=channel_announcement + node_signature_1=97eaa79c72eca400466390454cfaae9805e3e827a396e9f0d91c6abd0371f8136252dad20b56258a4955f78e9e76d063ec9cace9ac0735879fe60620f7502bc9 + node_signature_2=f1c432187bf0cf6629c7c99397f92153960630d2d766a2b59816c34c6a677a121414c20bf9dda865248112248fb0b017020e3676d6ebc6485c4056d55879d829 + bitcoin_signature_1=387ccb63e1dca46f1926de5b963500982eabe9a375d755a804ced67a3977253a2a3bbd525fa0de438b7dc39ec4939a7d81d9c832725005dca77c8fd4ac1dbfa0 + bitcoin_signature_2=0ea3ba77c7644cf34446f1c957cc95f9d2a6aa1abc939e4daddb180e3aa1b01f6c4613cbc9290cdbef74bbdd6a61da58e4ade784edc47795bab4514850f92fce + features= + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + node_id_1=02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 + node_id_2=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 + bitcoin_key_1=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a + bitcoin_key_2=021697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5 + +# To test if it accepted one of those channel_announcements, give it +# the matching channel_update, which should make it broadcast. +6. connect: privkey=0000000000000000000000000000000000000000000000000000000000000004 +7. recv: type=channel_update + signature=76df7e70c63cc2b63ef1c062b99c6d934a80ef2fd4dae9e1d86d277f47674af3255a97fa52ade7f129263f591ed784996eba6383135896cc117a438c80293282 + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x0 + timestamp=1565587763 + message_flags=0 + channel_flags=0 + cltv_expiry_delta=144 + htlc_minimum_msat=0 + fee_base_msat=1000 + fee_proportional_millionths=10 +8. recv: type=channel_update + signature=b236ed64ff6511baabba2b932e30da95e38c3d533e13870a96bb43150eb86a1453b00da41a5fc1ed5ae20f92c56812b40864996219b1e31188ae40e107e6140d + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x1x1 + timestamp=1565587763 + message_flags=0 + channel_flags=0 + cltv_expiry_delta=144 + htlc_minimum_msat=0 + fee_base_msat=1000 + fee_proportional_millionths=10 +9. recv: type=channel_update + signature=0bff9ee3b8e6ef8670b39817c21b9a6cc172ec47f0ea6b4aa4ae2469c3c352267969a0bc70cbdd441fb6f7e305b61cac6d1f16d5e042f8b72742c1d2c9a35e90 + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + short_channel_id=103x5x0 + timestamp=1565587763 + message_flags=0 + channel_flags=0 + cltv_expiry_delta=144 + htlc_minimum_msat=0 + fee_base_msat=1000 + fee_proportional_millionths=10 + +# New peer connects, asking for initial_routing_sync. We *won't* relay channel_announcement. +10. connect: privkey=0000000000000000000000000000000000000000000000000000000000000005 +11. expect-send: type=init +12. recv: type=init localfeatures=08 globalfeatures= +13. must-not-send: type=channel_announcement +14. must-not-send: type=channel_update diff --git a/tests/events/bolt7-10-gossip_timestamp_filter.events b/tests/events/bolt7-10-gossip_timestamp_filter.events new file mode 100644 index 000000000..bb25211cd --- /dev/null +++ b/tests/events/bolt7-10-gossip_timestamp_filter.events @@ -0,0 +1,135 @@ +# Tests for gossip_timestamp_filter. + +# Variables for some standard gossiping messages. +include setup.incl +1. block: $BLOCK_102 + +2. connect: privkey=0000000000000000000000000000000000000000000000000000000000000003 +3. expect-send: type=init +4. recv: type=init localfeatures= globalfeatures= + +5. block: $BLOCK_103 + +6. recv: $CHAN_ANN_103x1x0 +7. recv: $NODE_ANN_002 + +# New peer connects, asks for gossip_timestamp_filter=all. We *won't* relay channel_announcement, as there is no channel_update. +8. connect: privkey=0000000000000000000000000000000000000000000000000000000000000005 +9. expect-send: type=init +10. recv: type=init localfeatures= globalfeatures= +11. recv: type=gossip_timestamp_filter + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + first_timestamp=0 + timestamp_range=4294967295 +12. must-not-send: type=channel_announcement +13. must-not-send: type=node_announcement +14. disconnect: + +15. recv: $CHAN_UPDATE_103x1x0_002 + +# New peer connects, asks for gossip_timestamp_filter=all. update and node announcement will be relayed. +16. connect: privkey=0000000000000000000000000000000000000000000000000000000000000005 +17. expect-send: type=init +18. recv: type=init localfeatures= globalfeatures= +19. recv: type=gossip_timestamp_filter + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + first_timestamp=0 + timestamp_range=4294967295 +20. expect-send: $CHAN_ANN_103x1x0 +21. Any order: + 1. expect-send: $CHAN_UPDATE_103x1x0_002 + 1. expect-send: $NODE_ANN_002 +22. disconnect: + +# BOLT 7: +# The receiver: +# - SHOULD send all gossip messages whose `timestamp` is greater or +# equal to `first_timestamp`, and less than `first_timestamp` plus +# `timestamp_range`. + +23. connect: privkey=0000000000000000000000000000000000000000000000000000000000000005 +24. expect-send: type=init +25. recv: type=init localfeatures= globalfeatures= +26. recv: type=gossip_timestamp_filter + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + first_timestamp=1000 + timestamp_range=1565586763 +27. must-not-send: type=channel_announcement +28. must-not-send: type=channel_update +29. must-not-send: type=node_announcement +30. disconnect: + +31. connect: privkey=0000000000000000000000000000000000000000000000000000000000000005 +32. expect-send: type=init +33. recv: type=init localfeatures= globalfeatures= +34. recv: type=gossip_timestamp_filter + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + first_timestamp=1565587764 + timestamp_range=4294967295 +35. must-not-send: type=channel_announcement +36. must-not-send: type=channel_update +37. must-not-send: type=node_announcement +38. disconnect: + +# These two succeed in getting the gossip, then stay connected for next test. +39. connect: privkey=0000000000000000000000000000000000000000000000000000000000000005 +40. expect-send: type=init +41. recv: type=init localfeatures= globalfeatures= +42. recv: type=gossip_timestamp_filter + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + first_timestamp=1565587763 + timestamp_range=4294967295 +43. expect-send: $CHAN_ANN_103x1x0 +44. Any order: + 1. expect-send: $CHAN_UPDATE_103x1x0_002 + 1. expect-send: $NODE_ANN_002 + +45. connect: privkey=0000000000000000000000000000000000000000000000000000000000000006 +46. expect-send: type=init +47. recv: type=init localfeatures= globalfeatures= +48. recv: type=gossip_timestamp_filter + chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f + first_timestamp=1000 + timestamp_range=1565586764 +49. expect-send: $CHAN_ANN_103x1x0 +50. Any order: + 1. expect-send: $CHAN_UPDATE_103x1x0_002 + 1. expect-send: $NODE_ANN_002 + +# BOLT 7: +# - SHOULD restrict future gossip messages to those whose `timestamp` +# is greater or equal to `first_timestamp`, and less than +# `first_timestamp` plus `timestamp_range`. + +51. block: $BLOCK_109 + +52. recv: conn=0000000000000000000000000000000000000000000000000000000000000003 + $CHAN_ANN_109x1x0 + +53. recv: conn=0000000000000000000000000000000000000000000000000000000000000003 + $CHAN_UPDATE_109x1x0_004 + +54. recv: conn=0000000000000000000000000000000000000000000000000000000000000003 + $CHAN_UPDATE_109x1x0_005 + +55. recv: conn=0000000000000000000000000000000000000000000000000000000000000003 + $NODE_ANN_004 + +# 005's filter covers this, 006's doesn't. +56. expect-send: conn=0000000000000000000000000000000000000000000000000000000000000005 + $CHAN_ANN_109x1x0 + +57. Any order: + 1. expect-send: conn=0000000000000000000000000000000000000000000000000000000000000005 + $CHAN_UPDATE_109x1x0_004 + 1. expect-send: conn=0000000000000000000000000000000000000000000000000000000000000005 + $CHAN_UPDATE_109x1x0_005 + 1. expect-send: conn=0000000000000000000000000000000000000000000000000000000000000005 + $NODE_ANN_004 + +58. must-not-send: conn=0000000000000000000000000000000000000000000000000000000000000006 + type=channel_announcement +59. must-not-send: conn=0000000000000000000000000000000000000000000000000000000000000006 + type=channel_update +60. must-not-send: conn=0000000000000000000000000000000000000000000000000000000000000006 + type=node_announcement diff --git a/tests/events/bolt7-20-query_channel_range.events b/tests/events/bolt7-20-query_channel_range.events new file mode 100644 index 000000000..bb876d5e5 --- /dev/null +++ b/tests/events/bolt7-20-query_channel_range.events @@ -0,0 +1,98 @@ +# Tests for query_channel_range. + +# Note for gossip_channel_range: we are *allowed* to return a superset +# of what they ask, so if someone does that this test must be modified +# to accept it (add an option_IMPL_gossip_query_superset). +# +# Meanwhile, we assume an exact reply. + +include setup.incl +1. block: $BLOCK_102 + +# Our two channels. +2. block: $BLOCK_103 +3. block: $BLOCK_109 + +4. connect: privkey=0000000000000000000000000000000000000000000000000000000000000003 +5. expect-send: type=init +6. recv: type=init localfeatures= globalfeatures= +# They can send this, we'll ignore it. +7. maybe-send: type=gossip_timestamp_filter + +# Channel 103x1x0 (between 002 and 003) +8. recv: $CHAN_ANN_103x1x0 +9. recv: $CHAN_UPDATE_103x1x0_002 + +# Channel 109x1x0 (between 004 and 005) +10. recv: $CHAN_ANN_109x1x0 +11. recv: $CHAN_UPDATE_109x1x0_005 +12. recv: $CHAN_UPDATE_109x1x0_004 + +# New peer connects, with gossip_query option. +13. connect: privkey=0000000000000000000000000000000000000000000000000000000000000005 +14. expect-send: type=init +15. recv: type=init localfeatures=80 globalfeatures= +16. maybe-send: type=gossip_timestamp_filter + + # No queries? Must not get anything. + 1. must-not-send: type=channel_announcement + 2. must-not-send: type=channel_update + 3. must-not-send: type=node_announcement + + # This should elicit an empty response (we assume no zlib for that!) + 1. recv: type=query_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=0 number_of_blocks=103 option_gossip_queries + 2. One of: option_gossip_queries + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=0 number_of_blocks=103 encoded_short_ids=00 option_gossip_queries + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=0 number_of_blocks=103 encoded_short_ids=01789c030000000001 option_gossip_queries + + # This should get the first one, not the second. + 1. recv: type=query_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=1 option_gossip_queries + 2. One of: option_gossip_queries + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=1 encoded_short_ids=000000670000010000 option_gossip_queries + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=1 encoded_short_ids=01789c6360486760606460000002750069 option_gossip_queries + + # This should get the second one, not the first. + 1. recv: type=query_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=109 number_of_blocks=4294967295 option_gossip_queries + 2. One of: option_gossip_queries + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=109 number_of_blocks=4294967295 encoded_short_ids=0000006d0000010000 option_gossip_queries + # Could truncate number_of_blocks. + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=109 number_of_blocks=4294967187 encoded_short_ids=0000006d0000010000 option_gossip_queries + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=109 number_of_blocks=4294967295 encoded_short_ids=01789c6360c8656060646000000299006f option_gossip_queries + # Could truncate number_of_blocks. + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=109 number_of_blocks=4294967187 encoded_short_ids=01789c6360c8656060646000000299006f option_gossip_queries + + # This should get both. + 1. recv: type=query_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 option_gossip_queries + 2. One of: option_gossip_queries + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=00000067000001000000006d0000010000 option_gossip_queries + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=01789c6360486760606400825c300d00084e00d7 option_gossip_queries + + # This should get appended timestamp fields with option_gossip_queries_ex + 1. recv: type=query_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 tlvs=010101 option_gossip_queries + 2. One of: option_gossip_queries + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=00000067000001000000006d0000010000 option_gossip_queries !option_gossip_queries_ex + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=01789c6360486760606400825c300d00084e00d7 option_gossip_queries !option_gossip_queries_ex + # Timestamps may or may not be zlib encoded. + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=00000067000001000000006d0000010000 tlvs=0111005d50f933000000005d50f9355d50f934 option_gossip_queries option_gossip_queries_ex + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=00000067000001000000006d0000010000 tlvs=011601789c8b0df869cc0004b1013f4d81d804002b46058f option_gossip_queries option_gossip_queries_ex + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=01789c6360486760606400825c300d00084e00d7 tlvs=011601789c8b0df869cc0004b1013f4d81d804002b46058f option_gossip_queries option_gossip_queries_ex + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=01789c6360486760606400825c300d00084e00d7 tlvs=011601789c8b0df869cc0004b1013f4d81d804002b46058f option_gossip_queries option_gossip_queries_ex option_gossip_queries option_gossip_queries_ex + + # This should get appended checksum fields with option_gossip_queries_ex + 1. recv: type=query_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 tlvs=010102 option_gossip_queries + 2. One of: option_gossip_queries + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=00000067000001000000006d0000010000 option_gossip_queries !option_gossip_queries_ex + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=01789c6360486760606400825c300d00084e00d7 option_gossip_queries !option_gossip_queries_ex + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=00000067000001000000006d0000010000 tlvs=03101112fa3000000000f32ce9689bece840 option_gossip_queries option_gossip_queries_ex + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=01789c6360486760606400825c300d00084e00d7 tlvs=03101112fa3000000000f32ce9689bece840 option_gossip_queries option_gossip_queries_ex + + # This should append timestamps and checksums with option_gossip_queries_ex + 1. recv: type=query_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 tlvs=010103 option_gossip_queries + 2. One of: option_gossip_queries + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=00000067000001000000006d0000010000 option_gossip_queries !option_gossip_queries_ex + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=01789c6360486760606400825c300d00084e00d7 option_gossip_queries !option_gossip_queries_ex + # Timestamps may or may not be zlib encoded. + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=00000067000001000000006d0000010000 tlvs=0111005d50f933000000005d50f9355d50f93403101112fa3000000000f32ce9689bece840 option_gossip_queries option_gossip_queries_ex + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=00000067000001000000006d0000010000 tlvs=011601789c8b0df869cc0004b1013f4d81d804002b46058f03101112fa3000000000f32ce9689bece840 option_gossip_queries option_gossip_queries_ex + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=01789c6360486760606400825c300d00084e00d7 tlvs=0111005d50f933000000005d50f9355d50f93403101112fa3000000000f32ce9689bece840 option_gossip_queries option_gossip_queries_ex + 1. expect-send: type=reply_channel_range chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f first_blocknum=103 number_of_blocks=7 encoded_short_ids=01789c6360486760606400825c300d00084e00d7 tlvs=011601789c8b0df869cc0004b1013f4d81d804002b46058f03101112fa3000000000f32ce9689bece840 option_gossip_queries option_gossip_queries_ex diff --git a/tests/events/bolt7-25-query_short_channel_ids.events b/tests/events/bolt7-25-query_short_channel_ids.events new file mode 100644 index 000000000..8efdbdf61 --- /dev/null +++ b/tests/events/bolt7-25-query_short_channel_ids.events @@ -0,0 +1,124 @@ +# Tests for query_short_channel_ids. + +include setup.incl +1. block: $BLOCK_102 + +# Our three channels, and four nodes. +2. block: $BLOCK_103 +3. block: $BLOCK_109 +4. block: $BLOCK_115 + +5. connect: privkey=0000000000000000000000000000000000000000000000000000000000000003 +6. expect-send: type=init +7. recv: type=init localfeatures= globalfeatures= +# They can send this, we'll ignore it. +8. maybe-send: type=gossip_timestamp_filter + +# Channel 103x1x0 (between 002 and 003), only one update, both node_announce +9. recv: $CHAN_ANN_103x1x0 +10. recv: $CHAN_UPDATE_103x1x0_002 +11. recv: $NODE_ANN_002 +12. recv: $NODE_ANN_003 + +# Channel 109x1x0 (between 004 and 005): both updates, only one node_announce +13. recv: $CHAN_ANN_109x1x0 +# Node-announce first is legal +14. recv: $NODE_ANN_004 +15. recv: $CHAN_UPDATE_109x1x0_004 +16. recv: $CHAN_UPDATE_109x1x0_005 + +# Channel 115x1x0 (between 003 and 004): no updates. +17. recv: $CHAN_ANN_115x1x0 + +# New peer connects, with gossip_query option. +18. connect: privkey=0000000000000000000000000000000000000000000000000000000000000005 +19. expect-send: type=init +20. recv: type=init localfeatures=80 globalfeatures= +21. maybe-send: type=gossip_timestamp_filter + +# Query for non-existent channels (104x1x0 105x1x0 106x1x0 107x1x0) +22. recv: type=query_short_channel_ids chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f encoded_short_ids=000000680000010000000069000001000000006a000001000000006b0000010000 +23. expect-send: type=reply_short_channel_ids_end + +# zlib version +24. recv: type=query_short_channel_ids chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f encoded_short_ids=01789c6360c86060606400824c289d05a5b3c134001de001ab +25. expect-send: type=reply_short_channel_ids_end + +# Query for one channel (103x1x0) +26. recv: type=query_short_channel_ids chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f encoded_short_ids=000000670000010000 +27. expect-send: $CHAN_ANN_103x1x0 +28. Any order: + 1. expect-send: $CHAN_UPDATE_103x1x0_002 + 1. expect-send: $NODE_ANN_002 + 1. expect-send: $NODE_ANN_003 +29. expect-send: type=reply_short_channel_ids_end + +# Query for two channels (103x1x0 109x1x0) +30. recv: type=query_short_channel_ids chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f encoded_short_ids=00000067000001000000006d0000010000 +31. One of: # the channel_announcements must lead, then it gets messy. + 1. expect-send: $CHAN_ANN_103x1x0 + 2. Any order: # Not really *any* order, since ann must predate update. + 1. expect-send: $CHAN_UPDATE_103x1x0_002 + 1. expect-send: $NODE_ANN_002 + 1. expect-send: $NODE_ANN_003 + 1. expect-send: $CHAN_ANN_109x1x0 + 1. expect-send: $CHAN_UPDATE_109x1x0_004 + 1. expect-send: $CHAN_UPDATE_109x1x0_005 + 1. expect-send: $NODE_ANN_004 + 1. expect-send: $CHAN_ANN_109x1x0 + 2. Any order: + 1. expect-send: $CHAN_ANN_103x1x0 + 1. expect-send: $CHAN_UPDATE_103x1x0_002 + 1. expect-send: $NODE_ANN_002 + 1. expect-send: $NODE_ANN_003 + 1. expect-send: $CHAN_UPDATE_109x1x0_004 + 1. expect-send: $CHAN_UPDATE_109x1x0_005 + 1. expect-send: $NODE_ANN_004 +32. expect-send: type=reply_short_channel_ids_end + +# Query for specific things only, if supported. + +# Announce messages only. + 1. recv: type=query_short_channel_ids chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f encoded_short_ids=00000067000001000000006d0000010000 tlvs=0103000101 option_gossip_queries_ex + # zlib-encoded variant + 1. recv: type=query_short_channel_ids chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f encoded_short_ids=00000067000001000000006d0000010000 tlvs=010b01789c6364040000050003 option_gossip_queries_ex +33. Any order: option_gossip_queries_ex + 1. expect-send: $CHAN_ANN_103x1x0 option_gossip_queries_ex + 1. expect-send: $CHAN_ANN_109x1x0 option_gossip_queries_ex +34. expect-send: type=reply_short_channel_ids_end option_gossip_queries_ex + +# Node 1 channel_update messages only. + 1. recv: type=query_short_channel_ids chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f encoded_short_ids=00000067000001000000006d0000010000 tlvs=0103000202 option_gossip_queries_ex + # zlib-encoded variant + 1. recv: type=query_short_channel_ids chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f encoded_short_ids=00000067000001000000006d0000010000 tlvs=010b01789c6362020000080005 option_gossip_queries_ex + +35. Any order: option_gossip_queries_ex + 1. expect-send: $CHAN_UPDATE_103x1x0_002 option_gossip_queries_ex + 1. expect-send: $CHAN_UPDATE_109x1x0_005 option_gossip_queries_ex +36. expect-send: type=reply_short_channel_ids_end option_gossip_queries_ex + +# Node 2 channel_update messages only. + 1. recv: type=query_short_channel_ids chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f encoded_short_ids=00000067000001000000006d0000010000 tlvs=0103000404 option_gossip_queries_ex + # zlib-encoded variant + 1. recv: type=query_short_channel_ids chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f encoded_short_ids=00000067000001000000006d0000010000 tlvs=010b01789c63610100000e0009 option_gossip_queries_ex + +37. expect-send: $CHAN_UPDATE_109x1x0_004 option_gossip_queries_ex +38. expect-send: type=reply_short_channel_ids_end option_gossip_queries_ex + +# Node 1 announcements only. + 1. recv: type=query_short_channel_ids chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f encoded_short_ids=00000067000001000000006d0000010000 tlvs=0103000808 option_gossip_queries_ex + # zlib-encoded variant + 1. recv: type=query_short_channel_ids chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f encoded_short_ids=00000067000001000000006d0000010000 tlvs=010b01789ce3e00000001a0011 option_gossip_queries_ex + +39. expect-send: $NODE_ANN_002 option_gossip_queries_ex +40. expect-send: type=reply_short_channel_ids_end option_gossip_queries_ex + +# Node 2 announcements only. + 1. recv: type=query_short_channel_ids chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f encoded_short_ids=00000067000001000000006d0000010000 tlvs=0103001010 option_gossip_queries_ex + # zlib-encoded variant + 1. recv: type=query_short_channel_ids chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f encoded_short_ids=00000067000001000000006d0000010000 tlvs=010b01789c1310000000320021 option_gossip_queries_ex + +41. Any order: option_gossip_queries_ex + 1. expect-send: $NODE_ANN_003 option_gossip_queries_ex + 1. expect-send: $NODE_ANN_004 option_gossip_queries_ex +42. expect-send: type=reply_short_channel_ids_end option_gossip_queries_ex diff --git a/tests/events/setup.incl b/tests/events/setup.incl new file mode 100644 index 000000000..ba8d2ee94 --- /dev/null +++ b/tests/events/setup.incl @@ -0,0 +1,81 @@ +# Include this to create channels and set variables for gossip messages. + +# BLOCK_102 allows funding of channels with several UTXOs for easy testing. +# +# Here are the keys to spend funds, derived from BIP32 seed +# `0000000000000000000000000000000000000000000000000000000000000001`: +# +# pubkey 0/0/1: 02d6a3c2d0cf7904ab6af54d7c959435a452b24a63194e1c4e7c337d3ebbb3017b +# privkey 0/0/1: 76edf0c303b9e692da9cb491abedef46ca5b81d32f102eb4648461b239cb0f99 +# WIF 0/0/1: cRZtHFwyrV3CS1Muc9k4sXQRDhqA1Usgi8r7NhdEXLgM5CUEZufg +# P2WPKH 0/0/1: bcrt1qsdzqt93xsyewdjvagndw9523m27e52er5ca7hm +# UTXO: 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b/1 (0.01BTC) +# +# pubkey 0/0/2: 038f1573b4238a986470d250ce87c7a91257b6ba3baf2a0b14380c4e1e532c209d +# privkey 0/0/2: bc2f48a76a6b8815940accaf01981d3b6347a68fbe844f81c50ecbadf27cd179 +# WIF 0/0/2: cTtWRYC39drNzaANPzDrgoYsMgs5LkfE5USKH9Kr9ySpEEdjYt3E +# P2WPKH 0/0/2: bcrt1qlkt93775wmf33uacykc49v2j4tayn0yj25msjn +# UTXO: 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b/0 (0.02BTC) +# +# pubkey 0/0/3: 02ffef0c295cf7ca3a4ceb8208534e61edf44c606e7990287f389f1ea055a1231c +# privkey 0/0/3: 16c5027616e940d1e72b4c172557b3b799a93c0582f924441174ea556aadd01c +# WIF 0/0/3: cNLxnoJSQDRzXnGPr4ihhy2oQqRBTjdUAM23fHLHbZ2pBsNbqMwb +# P2WPKH 0/0/3: bcrt1q2ng546gs0ylfxrvwx0fauzcvhuz655en4kwe2c +# UTXO: 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b/3 (0.03BTC) +# +# pubkey 0/0/4: 026957e53b46df017bd6460681d068e1d23a7b027de398272d0b15f59b78d060a9 +# privkey 0/0/4: 53ac43309b75d9b86bef32c5bbc99c500910b64f9ae089667c870c2cc69e17a4 +# WIF 0/0/4: cQPMJRjxse9i1jDeCo8H3khUMHYfXYomKbwF5zUqdPrFT6AmtTbd +# P2WPKH 0/0/4: bcrt1qrdpwrlrmrnvn535l5eldt64lxm8r2nwkv0ruxq +# UTXO: 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b/4 (0.04BTC) +# +# pubkey 0/0/5: 03a9f795ff2e4c27091f40e8f8277301824d1c3dfa6b0204aa92347314e41b1033 +# privkey 0/0/5: 16be98a5d4156f6f3af99205e9bc1395397bca53db967e50427583c94271d27f +# WIF 0/0/5: cNLuxyjvR6ga2q6fdmSKxAd1CPQDShKV9yoA7zFKT7GJwZXr9MmT +# P2WPKH 0/0/5: bcrt1q622lwmdzxxterumd746eu3d3t40pq53p62zhlz +# UTXO: 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b/2 (49.89995320BTC) + +BLOCK_102=height=102 tx=020000000001017b8705087f9bddd2777021d2a1dfefc2f1c5afa833b5c4ab00ccc8a556d042830000000000feffffff0580841e0000000000160014fd9658fbd476d318f3b825b152b152aafa49bc9240420f000000000016001483440596268132e6c99d44dae2d151dabd9a2b2338496d2901000000160014d295f76da2319791f36df5759e45b15d5e105221c0c62d000000000016001454d14ae910793e930d8e33d3de0b0cbf05aa533300093d00000000001600141b42e1fc7b1cd93a469fa67ed5eabf36ce354dd6024730440220782128cb0319a8430a687c51411e34cfaa6641da9a8f881d8898128cb5c46897022056e82d011a95fd6bcb6d0d4f10332b0b0d1227b2c4ced59e540eb708a4b24e4701210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179865000000 + +# Funding tx spending 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b/1, feerate 253 to bitcoin privkeys 0000000000000000000000000000000000000000000000000000000000000010 and 0000000000000000000000000000000000000000000000000000000000000020 (txid 189c40b0728f382fe91c87270926584e48e0af3a6789f37454afee6c756031 +BLOCK_103=height=103 n=6 tx=020000000001016b85f654d8186f4d5dd32a977b2cf8c4b01ff4634152acba16b654c1c85a83160100000000ffffffff01c5410f0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d8187117382024730440220798d96d5a057b5b7797988a855217f41af05ece3ba8278366e2f69763c72e785022065d5dd7eeddc0766ddf65557c92b9c52c301f23f94d2cf681860d32153e6ae1e012102d6a3c2d0cf7904ab6af54d7c959435a452b24a63194e1c4e7c337d3ebbb3017b00000000 + +# This channel claimed by nodeids with privkeys ...002 and ...003. +CHAN_ANN_103x1x0=type=channel_announcement node_signature_1=63023be1b5b1f9fbb26fde890032bf4098fba6a78be75a8dd9deae332f6d20ec634806cc3477c41ca565c45089a8331beb3912fb896188b117d525ee17c85f63 node_signature_2=7f2c0664c6205e3c9626b4b7618d18235c059f13579a41dd79ae99e1234d5e8709d295e77c3846b37c44edc7fc4bd1ab07b605c0d216973b6bb4d9dead54b98e bitcoin_signature_1=083ccfe5a766dfe236446ddf52a4f89da5d3f3acc06851f2b0821223a069be02005f5cae7747451b8ae53709723c50fef2c7861c1b8b6bba1043e5bde56dbc39 bitcoin_signature_2=157a587d3495da5b953ba4a9f3a6ad8479a114e4bacbf4262dc257dd86f10db949e6e34e12ef95ead4ba5a9e38b86cd530920b7054914f1ee61ed4261783aa12 features= chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f short_channel_id=103x1x0 node_id_1=02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 node_id_2=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 bitcoin_key_1=03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a bitcoin_key_2=03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65 + +CHAN_UPDATE_103x1x0_002=type=channel_update signature=76df7e70c63cc2b63ef1c062b99c6d934a80ef2fd4dae9e1d86d277f47674af3255a97fa52ade7f129263f591ed784996eba6383135896cc117a438c80293282 chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f short_channel_id=103x1x0 timestamp=1565587763 message_flags=0 channel_flags=0 cltv_expiry_delta=144 htlc_minimum_msat=0 fee_base_msat=1000 fee_proportional_millionths=10 + +NODE_ANN_002=type=node_announcement signature=f48cc073f61994f978d6fc483cf477bdfd5c754d5deaf055af161fda9039831469432b5d4a08e95242498accf7324dc5918c8efe33dc5c65e17c90121c13320b features= timestamp=1565587763 node_id=02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 rgb_color=02c604 alias=3032633630343766393434316564376436643330343534303665393563303763 addresses=01080808082607 + +CHAN_UPDATE_103x1x0_003=type=channel_update signature=0b20265c60b98d6150097ea2ed73a0df4c870ed13defde348c799dd418671ca814837b7b46733d3f28f63b4f36768b44f6ec8dc52fbb08103e27c85ab1188c60 chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f short_channel_id=103x1x0 timestamp=1565587763 message_flags=1 channel_flags=1 cltv_expiry_delta=48 htlc_minimum_msat=0 fee_base_msat=100 fee_proportional_millionths=11 htlc_maximum_msat=100000 + +NODE_ANN_003=type=node_announcement signature=d0b8131bac61b20ecfd04f4ddd7042b98e140bc43ed5ab362ac29516bf0e7fce2c92b1e0f39de68afca2ab8cd1d1205a4847f3116c210b9352fba2d628c9b458 features= timestamp=1565587763 node_id=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 rgb_color=02f930 alias=3032663933303861303139323538633331303439333434663835663839643532 addresses=0151b6887026070220014c4e1cc141001e6f65fffec8a825260703c43068ceb641d7b25c3a26070441cf248da2034dfa9351a9e946d71ce86f561f50b67753fd8e385d44647bf62cdb91032607 + +# A later node-announcement, a little different. +NODE_ANN_003_LATER=type=node_announcement signature=9accff5a0d434eb09b5a3b594af3adc675e223f200a2d488947c6fca39115c885bf87b69963bcac430d0267ef15fe6f7abfa84d4b9be2bb0ee17822d1c02af41 features= timestamp=1565597764 node_id=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 rgb_color=02f930 alias=3032663933303861303139323538633331303439333434663835663839643532 addresses=0441cf248da2034dfa9351a9e946d71ce86f561f50b67753fd8e385d44647bf62cdb91032607 + +# Funding tx spending 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b/0, feerate 253 to bitcoin privkeys 0000000000000000000000000000000000000000000000000000000000000030 and 0000000000000000000000000000000000000000000000000000000000000040 (txid db029ee8cc511625887c192c5bb264249fe69b9b86eb627a52f9a313ba231ade) +BLOCK_109=height=109 n=6 tx=020000000001016b85f654d8186f4d5dd32a977b2cf8c4b01ff4634152acba16b654c1c85a83160000000000ffffffff0105841e0000000000220020fa73be60259cea454ee79a963514f0b7622db62eadc88daafe377bfa2aa30fbb0247304402205735b9750a90be1ca09cdf91d6697bde3746a390698ca754d516b56c72880bae02203c1deef3645cc20e300db1a808ffc7c2f57be200761ee3cf1a479d1e1aef70bc0121038f1573b4238a986470d250ce87c7a91257b6ba3baf2a0b14380c4e1e532c209d00000000 + +# This channel claimed by nodeids with privkeys ...004 and ...005. +CHAN_ANN_109x1x0=type=channel_announcement node_signature_1=764be32b3a8839a171a8ad9ef25d326d5c58160029006733ea06978e2806789024a1516575f69c957db8beeb3e5e1452e48db1b3ee085f3d623b47a986539783 node_signature_2=4f71e2785eb9d3833f307f8d954bc7b80f47bdcf483ff41ed9354143dbf62e1b50e31b9f735a26dc1d1ae78e857e0e727761faeaf60c9326cffd232f6ffd74e6 bitcoin_signature_1=8dd1cc39900c5728645b8a031e614b491abb36ff2aa3b529da7bce7091f28d6f237358c168f38a933ed483d9d582af45ee2b078ac9174751a9a4613c3fe4e8e7 bitcoin_signature_2=0bde268ccf1f1e7b245cd23d68e8bda0cb2fe42672bbe693a6a5cf85033fadbe069330dc785665ce8306946d00c16e40035e99db3daf4e1a087ca655f093b14a features= chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f short_channel_id=109x1x0 node_id_1=022f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4 node_id_2=02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13 bitcoin_key_1=03bf23c1542d16eab70b1051eaf832823cfc4c6f1dcdbafd81e37918e6f874ef8b bitcoin_key_2=026eca335d9645307db441656ef4e65b4bfc579b27452bebc19bd870aa1118e5c3 + +CHAN_UPDATE_109x1x0_004=type=channel_update signature=e4328bdcc06a311030d494ee391e000ca8bcdff59f0d071fce10253d43ba65e778c0540c11fb6417a43031da25c5a7b2c38122e92a7111760261967802128219 chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f short_channel_id=109x1x0 timestamp=1565587764 message_flags=0 channel_flags=1 cltv_expiry_delta=144 htlc_minimum_msat=0 fee_base_msat=1000 fee_proportional_millionths=10 + +NODE_ANN_004=type=node_announcement signature=189a566e9718c5ead7ac99956c0297b56c54bb304c99d3f02235712a376ad09f683cdd8d94d3c71c82fae2a08ea2495cca31426b6d4ec5ac35e83361c15633ef features= timestamp=1565587764 node_id=02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13 rgb_color=02e493 alias=3032653439336462663163313064383066333538316534393034393330623134 addresses= + +NODE_ANN_004_LATER=type=node_announcement signature=3370d9ada9e7b19e81425b32c2f05c5acb650f7ecb45ddb16eec922b1af956c23df932d7b13f6e7e0f230b1565df6ae7e0f7c4251d9a6805e3ef6057dd467cac features= timestamp=1565597765 node_id=02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13 rgb_color=02e493 alias=3032653439336462663163313064383066333538316534393034393330623134 addresses= + +CHAN_UPDATE_109x1x0_005=type=channel_update signature=06737e9e18d3e4d0ab4066ccaecdcc10e648c5f1c5413f1610747e0d463fa7fa39c1b02ea2fd694275ecfefe4fe9631f24afd182ab75b805e16cd550941f858c chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f short_channel_id=109x1x0 timestamp=1565587765 message_flags=1 channel_flags=0 cltv_expiry_delta=48 htlc_minimum_msat=0 fee_base_msat=100 fee_proportional_millionths=11 htlc_maximum_msat=100000 + +NODE_ANN_005=type=node_announcement signature=7a553b3933cb5974997c3e294a46ea474a435df2c0d82a0732c0c9700b04e2a6492b2a0620dcfd68e8e64c35b867bc3ec5df4393e3fc3b397095768e2362bae2 features= timestamp=1565587765 node_id=022f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4 rgb_color=022f8b alias=3032326638626465346431613037323039333535623461373235306135633531 addresses=022a03b0c0000300d000000000240020012607 + +# Funding tx spending 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b/3, feerate 253 to bitcoin privkeys 0000000000000000000000000000000000000000000000000000000000000050 and 0000000000000000000000000000000000000000000000000000000000000060 (txid 03330f41079aba9a595310c9c4d78676e5291ee6f1931dd7686f46ed16096186) +BLOCK_115=height=115 n=6 tx=020000000001016b85f654d8186f4d5dd32a977b2cf8c4b01ff4634152acba16b654c1c85a83160300000000ffffffff0145c62d00000000002200208225164b456194e9721a5ff5ea4df731d3d663f48f3ba96961dc9d0617ea2bf20247304402200bf2e7a300f8d268c9480732748707b36e43f6225f5330eca2cfa00b21c7159a02205390a3469a14b3a48714bb44db6d8ee838ef5e29b3063a32cba22a3a2d4f3e00012102ffef0c295cf7ca3a4ceb8208534e61edf44c606e7990287f389f1ea055a1231c00000000 + +# This channel claimed by nodeids with privkeys ...003 and ...004. +CHAN_ANN_115x1x0=type=channel_announcement node_signature_1=91d93a0ac557d03c0cb78b7699ad70ab2e86aed6e1780bd5381637bedbfe202938109484eee1a36a33aa7e0149fa062c502261564e4ecdbebdad5d32657efb82 node_signature_2=dc8cfdb6cdcde9e760f6b21f4d6ce7fe7569143aa253e1ae5339d96b9654422715ca0909f50b612818f9bb9e91fa4729d80d9fe3c16a9af821260a2c1c91888e bitcoin_signature_1=57543ea23aae8231dbe25a89ad1e6d32a4d17f27a84402d7535ec6af3d5c185645d98f605737bc7367660e6084f3d3a2ed2c8a6401feb71057d48f2de5f0961f bitcoin_signature_2=f19424a474fe2d1b573333d0783591a5478616d498f3331d6d0f32f570bce84862731442f0b1d04fa8f94a3bd639e8e7cb1ad5e96795b36f538ab45a90da4a90 features= chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f short_channel_id=115x1x0 node_id_1=02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13 node_id_2=02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 bitcoin_key_1=033f0e80e574456d8f8fa64e044b2eb72ea22eb53fe1efe3a443933aca7f8cb0e3 bitcoin_key_2=03e9623bbef1bf90ec0d7c744ed34659f010e6e638637161270ecd31e14f87f62e + +CHAN_UPDATE_115x1x0_003=type=channel_update signature=d920087673273a3221e6bf8671e1e3e0b20319c5dd87233c6525a90acaded2c032386032657daccf33e08e9aeb5a590300eb58a3943a89e73814bbf930d72391 chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f short_channel_id=115x1x0 timestamp=1565597764 message_flags=0 channel_flags=1 cltv_expiry_delta=144 htlc_minimum_msat=0 fee_base_msat=1000 fee_proportional_millionths=10 + +CHAN_UPDATE_115x1x0_004=type=channel_update signature=ca7bb2adea595eeb448c0139136196557f9f7b52ea0e3d85634bf8d7dd99096440e06e55d2874506ab6dd8d3b9285c0282dae498cb33146314084e37dbf2cff3 chain_hash=06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f short_channel_id=115x1x0 timestamp=1565597765 message_flags=1 channel_flags=0 cltv_expiry_delta=48 htlc_minimum_msat=0 fee_base_msat=100 fee_proportional_millionths=11 htlc_maximum_msat=100000 diff --git a/tests/events/test-spec.md b/tests/events/test-spec.md new file mode 100644 index 000000000..97f76597c --- /dev/null +++ b/tests/events/test-spec.md @@ -0,0 +1,204 @@ +# Format for Event-based Test Specifications. + +The programmatic test cases for the spec are a tree of events and +expected responses which test various scenarios described in the +specification. They serve only as guidelines: in some cases a +compliant implementation might produce a different response than that +given here, though that suggests further examination of the testcase, +the implementation, or both. + +## General Line Format + +FILE := SEQUENCE* + +SEQUENCE := SEQUENCE_LINE+ +SEQUENCE_LINE := SEQUENCE_STEP OPTION_SPEC* | META_LINE +SEQUENCE_STEP := INDENT4* NUMBER `.` SPACE+ EVENT_OR_SERIES OPTION_SPEC* + +EVENT_OR_SERIES := EVENT | `One of:` | `Any order:` +EVENT := INPUT_EVENT | OUTPUT_EVENT | `nothing` + +META_LINE := COMMENT | SPACE* | VARSET | INCLUDE + +COMMENT := `#` [SPACE|STRING]* +VARSET := IDENTIFIER`=`[SPACE|STRING]* OPTION_SPEC* +INCLUDE := `include` SPACE STRING OPTION_SPEC* + +Comment and blank lines are ignored. + +Variable lines set variables which can be expanded in any position with +a `$` prefix. There's currently no scope to variables. + +Include lines pull in other files, which is helpful for complex tests. + +Other lines are indented by multiples of 4 spaces; a line not indented +by a multiple of 4 is be joined to the previous line (this allows +nicer formatting for long lines). + +Each non-comment line indicates something to do to the implementation +(input event) or some response it should give (output event). + +Indentation indicates alternative sequences, eg. this reflects two tests, +STEP1->STEP2a->STEP3 and STEP1->STEP2b->STEP3: + + 1. STEP1 + 1. STEP2a + 1. STEP2b + 2. STEP3 + +An step must either have NUMBER 1, in which case it follows directly +from the parent, or NUMBER one greater than the previous step at the +same level, in which case it follows the previous. + +There must be exactly one top-level `1.` step. + +The special marker `Any order:` indicates that the following sequences +starting with distinct output events will occur, but might happen in +any order. This is useful for gossip messages which can be ordered in +multiple ways: + + 1. STEP1 + 2. Any order: + 1. STEP2a + 1. STEP2b + 1. STEP2c + +This means the test will accept STEP1->STEP2a->STEP2b->STEP2c, +STEP1->STEP2a->STEP2c->STEP2b, STEP1->STEP2b->STEP2a->STEP2c, +STEP1->STEP2b->STEP2c->STEP2a, STEP1->STEP2c->STEP2a->STEP2b, +or STEP1->STEP2c->STEP2b->STEP2c. + +The special marker `One of:` indicate sequences starting with distinct +output events, only one of which could occur. This is useful for optional +outputs which are more constrained, eg: + + 1. STEP1 + 2. One of: + 1. STEP2a + 2. STEP2b + 1. STEP2c + 2. STEP3 + +This means the test will accept STEP1->STEP2a->STEP2b->STEP3, or +STEP1->STEP2c->STEP3. + +## Option specifiers + +OPTION_SPEC := SPACE+ [`!`]OPTION_NAME +OPTION_NAME := `opt`IDENTIFIER[`/`ODD_OR_EVEN] +ODD_OR_EVEN := `odd` | `even` + +Some individual lines only apply if certain options are (not) supported. +If the implementation does not support the option (or does support the +option and it's preceeded by `!`), the line should be ignored. This +can be used to set/omit certain fields according to certain options, +or even whole steps. + +You can also filter by whether options are optional (`odd`) or +compulsory (`even`). + +## Input Events + +INPUT_EVENT := CONNECT | RECV | BLOCK | DISCONNECT | OPENCMD + +CONNECT := `connect:` SPACE+ CONNECT_OPTS +CONNECT_OPTS := `privkey=` HEX64 + +RECV := `recv:` [CONNSPEC] SPACE+ `type=` TYPENAME RECV_FIELDSPEC* +TYPENAME := IDENTIFIER|NUMBER +RECV_FIELDSPEC := SPACE+ IDENTIFIER`=`FIELDVALUE +FIELDVALUE := HEX | NUMBER + +BLOCK := `block:` `height=`NUMBER SPACE+ `n`=NUMBER SPACE+ [TX*] +TX := `tx=`HEXSTRING + +DISCONNECT := `disconnect:` SPACE+ CONNSPEC + +FUNDCHANCMD := `fundchannel:` [CONNSPEC] SPACE+ `amount=`NUMBER SPACE+ `utxo=`HEX`/`NUMBER + +INVOICECMD := `invoice:` SPACE+ `amount=`NUMBER SPACE+ `preimage=`HEX64 + +CONNSPEC := SPACE+ `conn=`HEX64 + +Input events are: +* `connect`: a connection established with another peer. These examples + assume a successful cryptographic handshake. We provide the private key. +* `recv`: an incoming message. The `type` is one of the message types + defined in the spec or a raw number. The other fields, if any, define + the individual fields: each non-optional field will be specified. Integer + fields can be specified as decimal integers, all other fields are hexidecimal + (note: this is confusing, as bitcoin usually reversed txids, and we don't!) + Length fields are not specified, but derived from the length of the hexidecimal + field. The special (hex) field `extra` indicates additional data to be appended. The optional `conn` argument allows you to specify which `connect` + you're referring to. The default is the last one. +* `block`: a generated block at a given height. Any `tx` specified + are to be placed in the (first) block. If `n` is more than 1, it's a short + cut for generating additional blocks. +* `disconnect`: a connection closed by a peer. +* `fundchannel`: tell the implementation to initiate the opening of a channel of the given `amount` of satoshis with the specific peer identified by `conn` (default, last `connect`). The funding comes from a single `utxo`, as specified by txid and output number. +* `invoice`: tell the implementation to accept a payment of `amount` msatoshis, with payment_preimage `preimage`. + +## Output Events + +OUTPUT_EVENT := EXPECT_SEND | MAYBE_SEND | MUST_NOT_SEND | EXPECT_TX | EXPECT_ERROR + +EXPECT_SEND := `expect-send:` [CONNSPEC] SPACE+ `type=` TYPENAME SPACE+ SEND_FIELDSPEC* +SEND_FIELDSPEC := IDENTIFIER`=`SPECVALUE +SPECVALUE := FIELDVALUE | HEX`/`HEX | `absent` | `*`LENGTH_RANGE +LENGTH_RANGE := `*`NUMBER | `*`NUMBER`-`NUMBER + +MAYBE_SEND := `maybe-send:` [CONNSPEC] SPACE+ `type=` TYPENAME SEND_FIELDSPEC* + +MUST_NOT_SEND := `must-not-send:` [CONNSPEC] SPACE+ `type=` TYPENAME SEND_FIELDSPEC* + +EXPECT_TX := `expect-tx:` SPACE+ `tx=`HEX + +EXPECT_ERROR := `expect-error:` [CONNSPEC] + +Output events are: +* `expect-send`: a message the implementation is expected to send. Any field specified must match exactly for the test to pass; the value`/`mask notation is used to compare bits against a mask; the field should be zero-padded for comparison if necessary. `*` is used to specify a length (in bytes) or a length range. The special field value `absent` means the (presumably optional) field must not be present. +* `maybe-send`: a message the implementation may send, at any point from now on (until the next `disconnect`) +* `must-not-send`: a message the implementation must not send, at any point from now on (until the next `disconnect`). This implies waiting at the end of the test (for a gossip flush!) to make sure it doesn't send it. +* `expect-tx`: a transaction the implementation is expected to broadcast. The transactions here assume deterministic signatures. +* `expect-error`: the implementation is expected to detect an error. This is generally a `expect-send` of `type=error` but it's legal for it to simply close the connection. If there's no `expect-error` event, the implementation is expected *not* to have an error. + + +## Test Node Setup + +The peer secret of the test node is assumed +`0000000000000000000000000000000000000000000000000000000000000001` +which makes its public key +`0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798`. + +The `minimum_depth` setting of the test node is assumed to be 3. + +The following secrets are used for the first channel (if successive +channels exist in tests, they are only used for gossip test and their +exact configuration is not tested); it's assumed that RFC6979 (using +HMAC-SHA256) is used to generate transaction signatures. + + funding_privkey: 0000000000000000000000000000000000000000000000000000000000000010 + revocation_basepoint_secret: 0000000000000000000000000000000000000000000000000000000000000011 + payment_basepoint_secret: 0000000000000000000000000000000000000000000000000000000000000012 + delayed_payment_basepoint_secret: 0000000000000000000000000000000000000000000000000000000000000013 + htlc_basepoint_secret: 0000000000000000000000000000000000000000000000000000000000000014 + per_commitment_secret_seed: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + + +## Blockchain Setup + +The initial blockchain is a bitcoind `regtest` chain, which has the +following initial blocks: + + Block 0 (genesis): 0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff7f20020000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000 + Block 1: 0000002006226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f7b8705087f9bddd2777021d2a1dfefc2f1c5afa833b5c4ab00ccc8a556d04283f5a1095dffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0200f2052a01000000160014751e76e8199196d454941c45d1b3a323f1433bd60000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000 + +The coinbase pays 50 BTC to the following key/address: + + privkey: 0000000000000000000000000000000000000000000000000000000000000001 + WIF: cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87JcbXMTcA + P2WPKH: bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080 + +A further 100 blocks are generated to allow the 50BTC output to be +spent, so block height is 101. The file `setup.incl` contains more +helpers for standard setups. diff --git a/tools/Makefile b/tools/Makefile new file mode 100644 index 000000000..19c680565 --- /dev/null +++ b/tools/Makefile @@ -0,0 +1,6 @@ +#! /usr/bin/make + +check: + @# E501 line too long (N > 79 characters) + @# W503: line break before binary operator + flake8 --ignore=E501,W503 test-events.py diff --git a/tools/test-events-clightning.py b/tools/test-events-clightning.py new file mode 100755 index 000000000..e330ab6a1 --- /dev/null +++ b/tools/test-events-clightning.py @@ -0,0 +1,331 @@ +#! /usr/bin/python3 +# This script exercises the c-lightning implementation + +# Released by Rusty Russell under CC0: +# https://creativecommons.org/publicdomain/zero/1.0/ + +import bitcoin +import bitcoin.rpc +import importlib +import lightning +import os +import shutil +import struct +import subprocess +import tempfile +import time + +from concurrent import futures +from ephemeral_port_reserve import reserve + +test = importlib.import_module('test-events') + +TIMEOUT = int(os.getenv("TIMEOUT", "30")) +LIGHTNING_SRC = os.getenv("LIGHTNING_SRC", '../lightning/') + + +def wait_for(success, timeout=TIMEOUT): + start_time = time.time() + interval = 0.25 + while not success() and time.time() < start_time + timeout: + time.sleep(interval) + interval *= 2 + if interval > 5: + interval = 5 + return time.time() <= start_time + timeout + + +# Stolen from lightning/tests/utils.py +class SimpleBitcoinProxy: + """Wrapper for BitcoinProxy to reconnect. + + Long wait times between calls to the Bitcoin RPC could result in + `bitcoind` closing the connection, so here we just create + throwaway connections. This is easier than to reach into the RPC + library to close, reopen and reauth upon failure. + """ + def __init__(self, btc_conf_file, *args, **kwargs): + self.__btc_conf_file__ = btc_conf_file + + def __getattr__(self, name): + if name.startswith('__') and name.endswith('__'): + # Python internal stuff + raise AttributeError + + # Create a callable to do the actual call + proxy = bitcoin.rpc.RawProxy(btc_conf_file=self.__btc_conf_file__) + + def f(*args): + return proxy._call(name, *args) + + # Make debuggers show rather than > + f.__name__ = name + return f + + +class Bitcoind(object): + """Starts regtest bitcoind on an ephemeral port, and returns the RPC proxy""" + def __init__(self, basedir): + self.bitcoin_dir = os.path.join(basedir, "bitcoind") + if not os.path.exists(self.bitcoin_dir): + os.makedirs(self.bitcoin_dir) + self.bitcoin_conf = os.path.join(self.bitcoin_dir, 'bitcoin.conf') + self.cmd_line = [ + 'bitcoind', + '-datadir={}'.format(self.bitcoin_dir), + '-server', + '-regtest', + '-logtimestamps', + '-nolisten'] + self.port = reserve() + print("Port is {}, dir is {}".format(self.port, self.bitcoin_dir)) + # For after 0.16.1 (eg. 3f398d7a17f136cd4a67998406ca41a124ae2966), this + # needs its own [regtest] section. + with open(self.bitcoin_conf, 'w') as f: + f.write("regtest=1\n") + f.write("rpcuser=rpcuser\n") + f.write("rpcpassword=rpcpass\n") + f.write("[regtest]\n") + f.write("rpcport={}\n".format(self.port)) + self.rpc = SimpleBitcoinProxy(btc_conf_file=self.bitcoin_conf) + + def start(self): + self.proc = subprocess.Popen(self.cmd_line, stdout=subprocess.PIPE) + + # Wait for it to startup. + while b'Done loading' not in self.proc.stdout.readline(): + pass + + # Block #1. + self.rpc.submitblock('0000002006226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f7b8705087f9bddd2777021d2a1dfefc2f1c5afa833b5c4ab00ccc8a556d04283f5a1095dffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0200f2052a01000000160014751e76e8199196d454941c45d1b3a323f1433bd60000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000') + self.rpc.generatetoaddress(100, self.rpc.getnewaddress()) + + + def stop(self): + self.proc.kill() + + def restart(self): + # Only restart if we have to. + if self.rpc.getblockcount() != 102 or self.rpc.getrawmempool() == []: + self.stop() + shutil.rmtree(os.path.join(self.bitcoin_dir, 'regtest')) + self.start() + + +class CLightningRunner(object): + def __init__(self, args): + self.connections = [] + directory = tempfile.mkdtemp(prefix='test-events-') + self.bitcoind = Bitcoind(directory) + self.bitcoind.start() + self.executor = futures.ThreadPoolExecutor(max_workers=20) + + self.lightning_dir = os.path.join(directory, "lightningd") + if not os.path.exists(self.lightning_dir): + os.makedirs(self.lightning_dir) + self.lightning_port = reserve() + + self.startup_flags = [] + for flag in args.startup_flags: + self.startup_flags.append("--{}".format(flag)) + + def start(self): + self.proc = subprocess.Popen(['{}/lightningd/lightningd'.format(LIGHTNING_SRC), + '--lightning-dir={}'.format(self.lightning_dir), + '--funding-confirms=3', + '--dev-force-privkey=0000000000000000000000000000000000000000000000000000000000000001', + '--dev-force-bip32-seed=0000000000000000000000000000000000000000000000000000000000000001', + '--dev-force-channel-secrets=0000000000000000000000000000000000000000000000000000000000000010/0000000000000000000000000000000000000000000000000000000000000011/0000000000000000000000000000000000000000000000000000000000000012/0000000000000000000000000000000000000000000000000000000000000013/0000000000000000000000000000000000000000000000000000000000000014/FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', + '--dev-bitcoind-poll=1', + '--dev-broadcast-interval=1000', + '--bind-addr=127.0.0.1:{}'.format(self.lightning_port), + '--network=regtest', + '--bitcoin-rpcuser=rpcuser', + '--bitcoin-rpcpassword=rpcpass', + '--bitcoin-rpcport={}'.format(self.bitcoind.port), + '--log-level=debug', + '--log-file=log'] + + self.startup_flags) + self.rpc = lightning.LightningRpc(os.path.join(self.lightning_dir, "lightning-rpc")) + + def node_ready(rpc): + try: + rpc.getinfo() + return True + except Exception: + return False + + if not wait_for(lambda: node_ready(self.rpc)): + raise subprocess.TimeoutExpired(self.proc, + "Could not contact lightningd") + + # Make sure that we see any funds that come to our wallet + for i in range(5): + self.rpc.newaddr() + + + def stop(self): + self.rpc.stop() + self.bitcoind.stop() + for c in self.connections: + c.proc.kill() + + def __enter__(self): + self.start() + return self + + def __exit__(self, type, value, tb): + self.stop() + + def restart(self): + self.rpc.stop() + self.bitcoind.restart() + for c in self.connections: + c.proc.kill() + + # Make a clean start + os.remove(os.path.join(self.lightning_dir, "gossip_store")) + os.remove(os.path.join(self.lightning_dir, "lightningd.sqlite3")) + os.remove(os.path.join(self.lightning_dir, "log")) + self.start() + + def connect(self, conn, line): + # FIXME: This serves to settle the gossip, eg tests/events/bolt7-20-query_channel_range.events fails without this. + time.sleep(1) + # FIXME: Open-code the lightning enc protocol in Python! + conn.proc = subprocess.Popen(['{}/devtools/gossipwith'.format(LIGHTNING_SRC), + '--privkey={}'.format(conn.connkey), + '--stdin', + '--no-init', + '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798@localhost:{}'.format(self.lightning_port)], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + bufsize=0) + + def getblockheight(self): + return self.bitcoind.rpc.getblockcount() + + def trim_blocks(self, newheight): + h = self.bitcoind.rpc.getblockhash(newheight + 1) + self.bitcoind.rpc.invalidateblock(h) + + def add_blocks(self, txs, n, line): + for tx in txs: + self.bitcoind.rpc.sendrawtransaction(tx) + self.bitcoind.rpc.generatetoaddress(n, self.bitcoind.rpc.getnewaddress()) + + if not wait_for(lambda: self.rpc.getinfo()['blockheight'] == self.getblockheight()): + raise test.ValidationError(line, + "Node did not sync to blockheight:" + " {} vs {}" + .format(self.rpc.getinfo()['blockheight'], + self.getblockheight())) + + def disconnect(self, conn, line): + # FIXME: Inject a bad enc packet, so it hangs up on us *after* + # processing + time.sleep(1) + conn.proc.terminate() + conn.proc.wait(30) + + def recv(self, conn, outbuf, line): + try: + rawl = struct.pack('>H', len(outbuf)) + conn.proc.stdin.write(rawl) + + while len(outbuf) != 0: + written = conn.proc.stdin.write(outbuf) + outbuf = outbuf[written:] + except BrokenPipeError: + # This happens when they've sent an error and closed; try + # reading it to figure out what went wrong. + fut = self.executor.submit(self._readmsg, conn) + try: + msg = fut.result(1) + except futures.TimeoutError: + msg = None + if msg: + raise test.ValidationError(line, "Connection closed after sending {}".format(msg.hex())) + else: + raise test.ValidationError(line, "Connection closed") + + + # FIXME: Implement fundchannel. + # We'll need to import privkey into bitcoind and hand-generate the tx + # then use fundchannel_start. + + def invoice(self, amount, preimage, line): + self.rpc.invoice(msatoshi=amount, + label=str(line), + description='invoice from {}'.format(line), + preimage=preimage) + + def _readmsg(self, conn): + rawl = conn.proc.stdout.read(2) + length = struct.unpack('>H', rawl)[0] + msg = bytes() + while len(msg) < length: + msg += conn.proc.stdout.read(length - len(msg)) + return msg + + def expect_send(self, conn, line, timeout=TIMEOUT): + fut = self.executor.submit(self._readmsg, conn) + try: + return fut.result(timeout) + except futures.TimeoutError: + raise test.ValidationError(line, "Timed out") + + def wait_for_finalmsg(self, conn): + # We told it to flush gossip every 1000msec, so give 2 seconds here. + while True: + fut = self.executor.submit(self._readmsg, conn) + try: + return fut.result(2) + except futures.TimeoutError: + return None + + def expect_tx(self, tx, line): + def tx_in_mempool(tx): + for txid in self.bitcoind.rpc.getrawmempool(): + if self.bitcoind.rpc.getrawtransaction(txid) == tx: + return True + return False + + # This tx should appear in the mempool. + if not wait_for(lambda: tx_in_mempool(tx)): + raise test.ValidationError(line, "Did not broadcast the transaction") + + def expect_error(self, conn, line): + while True: + msg = self.expect_send(conn, line) + + # If we got an error, mark it + if struct.unpack('>H', msg[0:2]) == (17,): + return + + def final_error(self): + # Just make sure it doesn't send an ERROR, but only give it 1 second. + # FIXME: We should just use poll to see if any output pending! + for c in self.connections: + try: + msg = self.expect_send(c, None, 1) + # If we got an error, mark it + if struct.unpack('>H', msg[0:2]) == (17,): + return msg.hex() + except test.ValidationError: + pass + return None + + +if __name__ == "__main__": + parser = test.setup_cmdline_options() + args = parser.parse_args() + # Here are the options we support. + args.option += subprocess.run(['{}/lightningd/lightningd'.format(LIGHTNING_SRC), + '--list-features-only'], + stdout=subprocess.PIPE, check=True).stdout.decode('utf-8').splitlines() + + # We use a context here, so we can always kill processes at exit + with CLightningRunner(args) as runner: + test.main(args, runner) diff --git a/tools/test-events.py b/tools/test-events.py new file mode 100755 index 000000000..7400622b0 --- /dev/null +++ b/tools/test-events.py @@ -0,0 +1,1722 @@ +#! /usr/bin/python3 +# This script exercises a lightning implementation using a JSON test case. + +# Released by Rusty Russell under CC0: +# https://creativecommons.org/publicdomain/zero/1.0/ + +import argparse +from copy import copy +import fileinput +import networkx as nx +from os import path +import re +import string +import struct +import sys +import matplotlib.pyplot as plt + +# Populated by read_csv +messages = [] + +# Populated by read_csv +tlvstreams = set() + +# From 01-messaging.md#fundamental-types: +name2size = {'byte': 1, + 'u16': 2, + 'u32': 4, + 'u64': 8, + 'short_channel_id': 8, + 'chain_hash': 32, + 'channel_id': 32, + 'sha256': 32, + 'preimage': 32, + 'secret': 32, + 'point': 33, + 'pubkey': 33, + 'signature': 64} + +name2structfmt = {'byte': 'B', + 'u16': '>H', + 'u32': '>I', + 'u64': '>Q', + 'short_channel_id': '>Q'} + + +def setup_cmdline_options(): + """Create an argparse.ArgumentParser for standard cmdline options""" + class OptionAction(argparse._AppendAction): + def __call__(self, parser, namespace, values, option_string=None): + if not values.endswith('/even') and not values.endswith('/odd'): + raise argparse.ArgumentTypeError("{} must end in /odd or /even" + .format(option_string)) + super().__call__(parser, namespace, values, option_string) + + parser = argparse.ArgumentParser() + parser.add_argument('csv_file', help='CSV file describing packet formats)') + parser.add_argument('input', nargs='*', default=[None], + help='Files to read in (or stdin)') + parser.add_argument('-v', '--verbose', help='Show working', + action="store_true") + parser.add_argument('--draw-events', help='Output ".png"', + action="store_true") + parser.add_argument('--exhaustive', help='Try all possible paths', + action="store_true") + parser.add_argument('--via', type=str, + help='Test shortest path via this specific [file:]line') + parser.add_argument('--flatten-failpath', help='Output a valid input file for the failing path', + action="store_true") + parser.add_argument('-o', '--option', action=OptionAction, default=[], + help='Indicate supported option') + parser.add_argument('-f', '--startup-flags', help="Pass these flags through to daemon " + "under test.\n'--' will be prepended.", + type=str, action="append", default=[]) + + return parser + + +class Line(object): + """Line of input from the testfile (could be multiple if they continue)""" + def __init__(self, filename, linestart, lineend, indentlevel, line): + self.filename = filename + self.linestart = linestart + self.lineend = lineend + self.indentlevel = indentlevel + self.line = line[:] + + def __copy__(self): + return Line(self.filename, self.linestart, self.lineend, + self.indentlevel, self.line) + + def __iadd__(self, other): + """+= two Lines: assumes they are adjacent.""" + if type(other) != Line: + return NotImplemented + # Tokens across filesystem boundaries (ie. include) don't add. + if other.filename == self.filename: + self.linestart = min(self.linestart, other.linestart) + self.lineend = max(self.lineend, other.lineend) + self.line += '\n' + other.line + return self + + def __str__(self): + # Human-readable line numbers are 1-based + if self.linestart == self.lineend: + return "{}:{}".format(self.filename, self.linestart + 1) + else: + return "{}:{}-{}".format(self.filename, self.linestart + 1, + self.lineend + 1) + + def __repr__(self): + return "Line " + self.__str__() + + def flatten(self, index, stopline, prefix): + print("{}# {}".format(prefix, self)) + parts = self.line.partition('.') + print("{}{}.{}".format(prefix, index, parts[2])) + return self == stopline, index + 1 + + +def pack(typename, v): + """Pack this value as this type""" + if typename in name2structfmt: + return struct.pack(name2structfmt[typename], v) + + # FIXME: This is our non-TLV code + if typename in tlvstreams: + return v + + if typename in Subtype.objs: + return Subtype.objs[typename].pack(v) + + # Pack directly as bytes + assert len(v) == name2size[typename] + return bytes(v) + + +def unpack_from(typename, bytestream, offset): + """Unpack from bytestream as this type. Returns len, value, or None, None""" + if typename in name2structfmt: + size = struct.calcsize(name2structfmt[typename]) + if size + offset > len(bytestream): + return None, None + return (size, struct.unpack_from(name2structfmt[typename], + bytestream, offset)[0]) + + # FIXME: This is our non-TLV code + if typename in tlvstreams: + return len(bytestream) - offset, bytestream[offset:] + + if typename in Subtype.objs: + subtype = Subtype.objs[typename] + return subtype.unpack(bytestream, offset) + + # Unpack directly as bytes + size = name2size[typename] + if size + offset > len(bytestream): + return None, None + return size, bytestream[offset:offset + size] + + +class ValidationError(Exception): + def __init__(self, line, message): + self.line = line + # Call the base class constructor with the parameters it needs + super().__init__(str(line) + ": Validation failed: " + message) + + +class LineError(Exception): + def __init__(self, line, message): + # Call the base class constructor with the parameters it needs + super().__init__(str(line) + ": Parsing failed:" + message) + + +# #### Dummy runner which you should replace with real one. #### +class DummyRunner(object): + def __init__(self, args): + self.verbose = args.verbose + pass + + def restart(self): + if self.verbose: + print("[RESTART]") + self.blockheight = 102 + + def connect(self, id, line): + if self.verbose: + print("[CONNECT {}]".format(line)) + + def getblockheight(self): + return self.blockheight + + def trim_blocks(self, newheight): + if self.verbose: + print("[TRIMBLOCK TO HEIGHT {}]".format(newheight)) + self.blockheight = newheight + + def add_blocks(self, txs, n, line): + if self.verbose: + print("[ADDBLOCKS {} WITH {} TXS]".format(n, len(txs))) + self.blockheight += n + + def disconnect(self, conn, line): + if self.verbose: + print("[DISCONNECT {}]".format(line)) + + def wait_for_finalmsg(self, conn): + if self.verbose: + print("[WAIT-FOR-FINAL]") + return None + + def recv(self, conn, outbuf, line): + if self.verbose: + print("[RECV {} {}]".format(line, outbuf.hex())) + + def fundchannel(self, conn, amount, txid, outnum, line): + if self.verbose: + print("[FUNDCHANNEL TO {} for {} with UTXO {}/{} {}]" + .format(conn, amount, txid, outnum, line)) + + def invoice(self, amount, preimage, line): + if self.verbose: + print("[INVOICE for {} with PREIMAGE {} {}]" + .format(amount, preimage, line)) + + def expect_send(self, conn, line): + if self.verbose: + print("[EXPECT-SEND {}]".format(line)) + # return bytes.fromhex(input("{}? ".format(line))) + + def expect_tx(self, tx, line): + if self.verbose: + print("[EXPECT-TX {} {}]".format(tx.hex(), line)) + + def expect_error(self, conn, line): + if self.verbose: + print("[EXPECT-ERROR {}]", line) + + def final_error(self): + if self.verbose: + print("[EXPECT NO ERROR]") + return None + +# #### End dummy runner which you should replace with real one. #### + + +class Field(object): + def __init__(self, message, name, typename, count, options): + self.message = message + self.name = name + self.typename = typename + self.options = options + self.islenvar = False + # This contains all the integer types: otherwise it's a hexstring, + self.isinteger = (typename in name2structfmt and + not (typename == 'byte' and count)) + + # This is set for static-sized array. + self.arraylen = None + # This is set for variable-sized array. + self.arrayvar = None + + if count: + # If array is a variable, must be prior field. + try: + self.arraylen = int(count) + except ValueError: + self.arrayvar = message.findField(count) + self.arrayvar.islenvar = True + + def is_optional(self): + """TLVs are always considered optional""" + return self.options != [] or self.typename in tlvstreams + + @staticmethod + def field_from_str(line, typename, isinteger, s): + if typename == "short_channel_id": + parts = s.split('x') + if len(parts) != 3: + raise LineError(line, "short_channel_id should be NxNxN") + try: + return ((int(parts[0]) << 40) + | (int(parts[1]) << 16) | (int(parts[2]))) + except ValueError: + raise LineError(line, "short_channel_id should be xx") + # Int variants + if isinteger: + try: + v = int(s) + except ValueError: + raise LineError(line, "{} should be integer".format(typename)) + + if v >= (1 << (name2size[typename] * 8)): + raise LineError(line, "{} must be < {} bytes" + .format(typename, name2size[typename])) + return v + + # Everything else is a hex string. + try: + v = bytes.fromhex(s) + except ValueError: + raise LineError(line, "Non-hex value for {}: '{}'" + .format(typename, s)) + + # FIXME: This is our non-TLV code + if typename in tlvstreams: + return v + + if len(v) != name2size[typename]: + raise LineError(line, "{} must be {} bytes long not {}" + .format(typename, name2size[typename], len(v))) + return v + + def field_value(self, line, value): + """Decodes a value for this field: returns (fieldvalue, arrsize) + or (fieldvalue, None) if not an array""" + # If it's an array, expect a JSON array unless it's a byte array. + if self.arraylen or self.arrayvar: + if self.typename == 'byte': + try: + v = bytes.fromhex(value) + except ValueError: + if value.startswith('*'): + v = value + return v, v + raise LineError(line, + "Non-hex value for {} byte array: '{}'" + .format(self.name, value)) + # Known length? Check + if self.arraylen and len(v) != self.arraylen: + raise LineError(line, + "{} byte array should be length {} not {}" + .format(self.name, self.arraylen, len(v))) + return v, len(v) + elif self.typename in tlvstreams: + v = bytes.fromhex(value) + return v, len(v) + elif self.typename in Subtype.objs: # Subtypes + subtype = Subtype.objs[self.typename] + return subtype.parse(line, value) + else: + arr = [] + # Empty string doesn't quite do what we want with split. + if value == '': + values = [] + else: + values = value.split(',') + for v in values: + arr += [self.field_from_str(line, self.typename, + self.isinteger, v)] + # Known length? Check + if self.arraylen and len(arr) != self.arraylen: + raise LineError(line, + "{} array should be length {} not {}" + .format(self.name, self.arraylen, len(v))) + return arr, len(arr) + else: + return (self.field_from_str(line, + self.typename, self.isinteger, value), + None) + + def __repr__(self): + s = "{}:{}".format(self.name, self.typename) + if self.arraylen: + s += "[{}]".format(self.arraylen) + elif self.arrayvar: + s += "[{}]".format(self.arrayvar.name) + return s + + +class Message(object): + # * 0x8000 (BADONION): unparsable onion encrypted by sending peer + # * 0x4000 (PERM): permanent failure (otherwise transient) + # * 0x2000 (NODE): node failure (otherwise channel) + # * 0x1000 (UPDATE): new channel update enclosed + onion_types = {'BADONION': 0x8000, + 'PERM': 0x4000, + 'NODE': 0x2000, + 'UPDATE': 0x1000} + + def __init__(self, name, value): + self.name = name + self.value = self.parse_value(value) + self.fields = [] + + def parse_value(self, value): + result = 0 + for token in value.split('|'): + if token in self.onion_types.keys(): + result |= self.onion_types[token] + else: + result |= int(token) + + return result + + def findField(self, fieldname): + for f in self.fields: + if f.name == fieldname: + return f + return None + + def addField(self, field): + self.fields.append(field) + + def __repr__(self): + return "{}:{}:{}".format(self.name, self.value, self.fields) + + +def find_message(messages, name): + for m in messages: + if m.name == name: + return m + + return None + + +class Subtype(Message): + objs = {} + + def __init__(self, name): + Message.__init__(self, name, '0') + + def parse(self, line, s): + """ Given an input line for a subtype, parse it into a dict + of fields for that subtype """ + if len(s) == 0: + return b'', 0 + + if s[0] == '[': + i = 1 + arr = [] + while i < len(s) and s[i] != ']': + end, obj = self._parse_obj(line, s[i:]) + arr.append(obj) + i += end + if i < len(s) and s[i] == ',': + i += 1 + return arr, len(arr) + else: + _, obj = self.parse_obj(line, s) + return obj, None + + def _parse_obj(self, line, s): + if s[0] != '{': + raise LineError(line, "Subtype formatted incorrectly. got {} when expecting an open bracket ({},{})" + .format(s[0], self.name, s)) + + end, fields = self.find_fields(s) + if end < 0: + raise LineError(line, "Subtype formatted incorrectly. No end bracket found ({}, {})" + .format(self.name, s)) + + val = {} + for f_name, f_val in fields: + sub_field = self.findField(f_name) + + if not sub_field: + raise LineError(line, "{} subtype error. Unable to find field {}" + .format(self.name, f_name)) + + val[f_name], vararrlen = sub_field.field_value(line, f_val) + if vararrlen is not None: + val[sub_field.arrayvar.name] = vararrlen + + return end + 1, val + + def find_fields(self, s): + """ Handle nested arrays + objects. Returns set of fields for + the upper most object and the 'end' count of where this object ends. + {abc=[{},{}],bcd=[{},{}],...],abc=[]},{abc=[{},{}]}... """ + arr_count = 0 + bracket_count = 0 + end = len(s) + field_set = [] + i = 0 + field = '' + tok = None + while i < end: + if s[i] == '[': + arr_count += 1 + field += s[i] + elif s[i] == ']': + arr_count -= 1 + field += s[i] + elif s[i] == '{': + bracket_count += 1 + if i != 0: + field += s[i] + elif s[i] == '}': + bracket_count -= 1 + if bracket_count == 0: + field_set.append((tok, field)) + return i, field_set + else: + field += s[i] + elif s[i] == ',': + if bracket_count == 1 and arr_count == 0: + field_set.append((tok, field)) + field = '' + tok = None + else: + field += s[i] + elif s[i] == '=': + if not tok: + tok = field + field = '' + else: + field += s[i] + else: + field += s[i] + + i += 1 + return -1, None + + def pack(self, values): + """ We need to return bytes for each field """ + bites = bytes([]) + for f in self.fields: + if f.name in values: + val = values[f.name] + if f.arrayvar or f.arraylen: + for a in val: + bites += pack(f.typename, a) + else: + bites += pack(f.typename, val) + return bites + + def unpack(self, bytestream, offset): + """ For every field, unpack it""" + result = {} + lenfields = {} + offset_start = offset + for f in self.fields: + offset, v = unpack_field(f, lenfields, bytestream, offset) + result[f.name] = v + + return offset - offset_start, result + + def compare(self, msgname, vals, expected): + if not bool(expected): + if bool(vals): + return ("Nothing expected for {}.{} but returned {}" + .format(msgname, self.name, vals)) + return None + for name, exp_val in expected.items(): + if name not in vals: + return ("Expected field {}.{}.{} " + "not present in values" + .format(msgname, self.name, name)) + + f = self.findField(name) + if not f: + return ("Field {} is not known for subtype {}({})" + .format(name, self.name, msgname)) + + val = vals[name] + err = compare_results(msgname + "." + self.name, f, val, exp_val) + if err is not None: + return err + + return None + + +def unpack_field(field, lenfields, bytestream, offset): + # If it's an array, we need the whole thing. + if field.arrayvar or field.arraylen: + if field.arrayvar: + num = lenfields[field.arrayvar.name] + else: + num = field.arraylen + # Array of bytes is special: treat raw. + if field.typename == 'byte': + v = bytestream[offset:offset + num] + offset += num + else: + v = [] + for i in range(0, num): + size, var = unpack_from(field.typename, bytestream, offset) + if size is None: + raise ValueError('Response too short to extract {}[{}]: {}' + .format(field.name, i, bytestream.hex())) + offset += size + v += [var] + else: + size, v = unpack_from(field.typename, bytestream, offset) + if size is None: + # Optional fields might not exist + if field.is_optional(): + v = None + size = 0 + else: + raise ValueError('Response too short to extract {} {} ({}): {}' + .format(field.name, field.typename, offset, v)) + offset += size + + # If it's used as a length, save it. + if field.islenvar: + lenfields[field.name] = int(v) + + return offset, v + + +def read_csv(args): + for line in fileinput.input(args.csv_file): + parts = line.rstrip().split(',') + + if parts[0] == 'msgtype': + # eg msgtype,commit_sig,132 + messages.append(Message(parts[1], parts[2])) + elif parts[0] == 'msgdata': + m = find_message(messages, parts[1]) + if m is None: + raise ValueError('Unknown message {}'.format(parts[1])) + + # eg. msgdata,channel_reestablish,your_last_per_commitment_secret + # ,secret,,1option209 + m.addField(Field(m, parts[2], parts[3], parts[4], parts[5:])) + elif parts[0] == 'subtype': + Subtype.objs[parts[1]] = Subtype(parts[1]) + elif parts[0] == 'subtypedata': + if parts[1] not in Subtype.objs: + raise ValueError('Unknown subtype {}'.format(parts[1])) + # Insert fields into dict for subtype + subtype = Subtype.objs[parts[1]] + subtype.addField(Field(subtype, parts[2], parts[3], parts[4], parts[5:])) + elif parts[0] == 'tlvtype': + tlvstreams.add(parts[1]) + + +def line_keyval(line, part): + """Return , from key=val part of line, or raise LineError""" + p = part.partition('=') + if p[1] != '=': + raise LineError(line, "Malformed key {} does not contain '='" + .format(part)) + return p[0], p[2] + + +def parse_params(line, parts, compulsorykeys, optionalkeys=[]): + """Given an array of = make a dict, checking we have all compulsory +# keys.""" + ret = {} + for i in parts: + k, v = line_keyval(line, i) + if k in ret.keys(): + raise LineError(line, "Duplicate key {}".format(k)) + if k in compulsorykeys: + compulsorykeys.remove(k) + elif k in optionalkeys: + optionalkeys.remove(k) + else: + raise LineError(line, "Unknown key {}".format(k)) + ret[k] = v + + if compulsorykeys != []: + raise LineError(line, "No specification for key {}" + .format(compulsorykeys[0])) + return ret + + +def check_hex(line, val, digits): + if not all(c in string.hexdigits for c in val): + raise LineError(line, "{} is not valid hex".format(val)) + if len(val) != digits: + raise LineError(line, "{} not {} characters long".format(val, digits)) + + +class Connection(object): + """Trivial class to represent a connection: often decorated by others""" + def __init__(self, connkey): + self.connkey = connkey + self.maybe_sends = [] + self.must_not_sends = [] + + def __str__(self): + return str(self.connkey) + + +def optional_connection(line, params): + """Trivial helper to return & remove conn=key if specified, None if not""" + ret = params.pop('conn', None) + if ret is not None: + check_hex(line, ret, 64) + return ret + + +def optional_connection_then_type(line, parts): + """Trivial helper to extract & remove conn= and type= from parts""" + if len(parts) < 1: + raise LineError(line, "Missing type=") + + k, v = line_keyval(line, parts.pop(0)) + if k == 'conn': + check_hex(line, v, 64) + conn = v + if len(parts) < 1: + raise LineError(line, "Missing type=") + k, v = line_keyval(line, parts.pop(0)) + else: + conn = None + + if k != 'type': + raise LineError(line, "Expected type=") + return conn, v + + +def which_connection(line, runner, connkey): + """Helper to get the conn they asked for, or default if connkey=None""" + if connkey is None: + if len(runner.connections) == 0: + raise LineError(line, "No active 'connect'") + return runner.connections[-1] + for c in runner.connections: + if c.connkey == connkey: + return c + raise LineError(line, "No active 'connect' {}".format(connkey)) + + +def end_connection(runner, conn, line): + """Helper to wait to see if any must-not-send are triggered at end""" + if conn.must_not_sends == []: + return + + # We assume we don't get an infinite stream of msgs! + while True: + msg = runner.wait_for_finalmsg(conn) + if msg is None: + return + for m in conn.must_not_sends: + if message_match(m.expectmsg, m.expectfields, msg) is None: + raise ValidationError(line, "must-not-send at {} violated by {}" + .format(m.line, msg.hex())) + + # If it was an (unexpected) error, we've failed. + if not runner.expected_error and struct.unpack('>H', msg[0:2]) == (17,): + raise ValidationError(line, + "Unexpected error occurred: {}".format(msg.hex())) + + +class NothingEvent(object): + def __init__(self, line, parts): + parse_params(line, parts, []) + + def action(self, runner, line): + pass + + +class ConnectEvent(object): + def __init__(self, line, parts): + self.privkey = parse_params(line, parts, ['privkey'])['privkey'] + check_hex(line, self.privkey, 64) + + def action(self, runner, line): + conn = Connection(self.privkey) + if conn.connkey in [c.connkey for c in runner.connections]: + raise LineError(line, + "Already have connection to {}".format(conn.connkey)) + runner.connections.append(conn) + runner.connect(conn, line) + + +class DisconnectEvent(object): + def __init__(self, line, parts): + d = parse_params(line, parts, [], ['conn']) + self.connkey = optional_connection(line, d) + + def action(self, runner, line): + conn = which_connection(line, runner, self.connkey) + + end_connection(runner, conn, line) + runner.disconnect(conn, line) + runner.connections.remove(conn) + + +class RecvEvent(object): + def __init__(self, line, parts): + self.connkey, t = optional_connection_then_type(line, parts) + + msg = find_message(messages, t) + if not msg: + # Allow raw integers. + msg = Message('unknown', t) + + # See what fields are allowed. + fields = [] + optfields = ['extra'] + for f in msg.fields: + # Lengths are implied + if f.islenvar: + continue + # Optional fields are, um, optional. + if f.is_optional(): + optfields.append(f.name) + else: + fields.append(f.name) + + # This fails if non-optional fields aren't specified. + d = parse_params(line, parts, fields, optfields) + + # Now get values for assembling the message. + values = {} + for f in msg.fields: + # Lengths are implied + if f.islenvar: + continue + if f.name not in d: + continue + value, vararrlen = f.field_value(line, d[f.name]) + values[f.name] = value + if f.arrayvar: + values[f.arrayvar.name] = vararrlen + + # BOLT #1: + # After decryption, all Lightning messages are of the form: + # + # 1. `type`: a 2-byte big-endian field indicating the type of message + # 2. `payload`: a variable-length payload that comprises the remainder + # of the message and that conforms to a format matching the `type` + self.b = struct.pack(">H", msg.value) + for f in msg.fields: + if f.name not in values: + continue + + v = values[f.name] + if f.arrayvar or f.arraylen: + for a in v: + self.b += pack(f.typename, a) + else: + self.b += pack(f.typename, v) + + if 'extra' in d: + self.b += bytes.fromhex(d['extra']) + + def action(self, runner, line): + runner.recv(which_connection(line, runner, self.connkey), + self.b, line) + +def compare_results(msgname, f, v, exp): + """ f -> field; v -> value; exp -> expected value """ + + # If they specify field=absent, it must not be there. + if exp is None: + if v is not None: + return "Field {} is present".format(f.name) + else: + return None + + if v is None: + return ("Optional field {} is not present" + .format(f.name)) + if isinstance(exp, tuple): + # Out-of-range bitmaps are considered 0 (eg. feature tests) + if len(v) < len(exp[0]): + cmpv = b'\x00' * (len(exp[0]) - len(v)) + v + elif len(v) > len(exp[0]): + cmpv = v[-len(exp[0]):] + else: + cmpv = v + + for i in range(0, len(exp[0])): + if cmpv[i] & exp[1][i] != exp[0][i]: + return ("Expected {}.{} mask 0x{}" + " value 0x{} but got 0x{}" + " (offset {} different)" + .format(msgname, f.name, + exp[1].hex(), exp[0].hex(), + v.hex(), len(exp[0]) - 1 - i)) + # Use subtype comparer + elif f.typename in Subtype.objs: + if not v and not exp: + return None + return Subtype.objs[f.typename].compare(msgname, v[0], exp[0]) + + # Simple comparison + elif v != exp: + if f.isinteger: + # Instead of checking a field's value, allow a test + # to specify a range of bytelen that's valid. + # This is needed for witness data verifications. + # e.g. *71-73 or *73 for exactly 73 bytes + if isinstance(exp, str) and exp.startswith('*') and check_range(exp[1:], v): + return None + valstr = str(v) + expectstr = str(exp) + # Same as above note about a range of length + elif isinstance(exp,str) and exp.startswith('*'): + if check_range(exp[1:], len(v.hex()) // 2): + return None + expectstr = "result of bytelen {}".format(exp[1:]) + valstr = str(len(v.hex()) // 2) + else: + valstr = v.hex() + expectstr = exp.hex() + return ("Expected {}.{} {} but got {}" + .format(msgname, + f.name, expectstr, valstr)) + return None + + +def check_range(exp, val_len): + len_range = exp.split('-') + if len(len_range) > 2: + raise ValueError("Expected size range invalid", exp) + + if len(len_range) == 1: + return int(len_range[0]) == val_len + + return int(len_range[0]) <= val_len and int(len_range[1]) >= val_len + +def message_match(expectmsg, expectfields, b): + """Internal helper to see if b matches expectmsg & expectfields. + + Returns explanation string if it didn't match, otherwise None.""" + msgtype = struct.unpack_from(">H", b)[0] + off = 2 + + if msgtype != expectmsg.value: + return "Expected msg {} but got {}: {}".format(expectmsg.name, + msgtype, b.hex()) + # Keep length fields + lenfields = {} + for f in expectmsg.fields: + off, v = unpack_field(f, lenfields, b, off) + + # They expect a value from this. + if f.name in expectfields: + exp = expectfields[f.name] + err = compare_results(expectmsg.name, f, v, exp) + if err is not None: + return err + ": {}".format(b.hex()) + + return None + + +def maybesend_match(conn, msg): + """Internal helper to see if msg matches one of the previous maybe-sends""" + for m in conn.maybe_sends: + failreason = message_match(m.expectmsg, m.expectfields, msg) + if failreason is None: + conn.maybe_sends.remove(m) + return True + + return False + + +class ExpectSendEvent(object): + def __init__(self, line, parts, maybe=False, mustnot=False): + self.line = line + self.maybe = maybe + self.mustnot = mustnot + + self.connkey, t = optional_connection_then_type(line, parts) + + self.expectmsg = find_message(messages, t) + if not self.expectmsg: + raise LineError(line, "Unknown message type") + self.expectfields = {} + + optfields = [] + for f in self.expectmsg.fields: + # Lengths are implied + if f.islenvar: + continue + optfields.append(f.name) + + # All fields are optional + d = parse_params(line, parts, [], optfields) + + for v in d.keys(): + # IDENTIFIER`=`FIELDVALUE | IDENTIFIER`=`HEX/HEX | `absent` + f = self.expectmsg.findField(v) + + parts = d[v].partition('/') + if parts[1] == '/': + self.expectfields[v] = (bytes.fromhex(parts[0]), + bytes.fromhex(parts[2])) + if len(self.expectfields[v][0]) != len(self.expectfields[v][1]): + raise LineError(line, "Unequal value/mask lengths") + else: + if parts[0] == 'absent': + if not f.is_optional(): + raise LineError(line, "{} is not optional".format(f.name)) + self.expectfields[v] = None + else: + self.expectfields[v], _ = f.field_value(line, parts[0]) + + def __repr__(self): + if self.mustnot: + return "must-not-send:{}:{}".format(self.expectmsg.name, self.line) + if self.maybe: + return "maybe-send:{}:{}".format(self.expectmsg.name, self.line) + return "expect-send:{}:{}".format(self.expectmsg.name, self.line) + + def action(self, runner, line): + conn = which_connection(line, runner, self.connkey) + # If this is 'maybe-send' then just add it to maybe list. + if self.maybe: + conn.maybe_sends.append(self) + return + # If this is 'must-not-send' then just add it to maybe list. + elif self.mustnot: + conn.must_not_sends.append(self) + return + + msg = runner.expect_send(conn, line) + + # We let the dummy runner "pass" always. + if type(runner) == DummyRunner: + return + + while True: + failreason = message_match(self.expectmsg, self.expectfields, msg) + if failreason is None: + return + + if maybesend_match(conn, msg): + msg = runner.expect_send(conn, line) + else: + break + + if conn.maybe_sends != []: + raise ValidationError(line, + failreason + + " (and none of {})".format(conn.maybe_sends)) + raise ValidationError(line, failreason) + + +class BlockEvent(object): + def __init__(self, line, parts): + # Since parse_params doesn't allow dups, feed it one part at a time + self.blockheight = int(parse_params(line, [parts[0]], ['height'])['height']) + self.txs = [] + self.n = 1 + + # Since parse_params doesn't allow dups, feed it one part at a time + for i in range(1, len(parts)): + # n is only valid as first arg. + if i == 1: + d = parse_params(line, [parts[i]], [], ['n', 'tx']) + if 'n' in d: + if self.n != 1: + raise LineError(line, "Can't specify n more than once") + self.n = int(d['n']) + continue + else: + d = parse_params(line, [parts[i]], ['tx']) + self.txs.append(d['tx']) + + def action(self, runner, line): + # Oops, did they ask us to produce a block with no predecessor? + if runner.getblockheight() + 1 < self.blockheight: + raise LineError(line, "Cannot generate block #{} at height {}". + format(self.blockheight, runner.getblockheight())) + + # Throw away blocks we're replacing. + if runner.getblockheight() >= self.blockheight: + runner.trim_blocks(self.blockheight - 1) + + # Add new one + runner.add_blocks(self.txs, self.n, line) + assert runner.getblockheight() == self.blockheight - 1 + self.n + + +class ExpectTxEvent(object): + def __init__(self, line, parts): + self.tx = bytes.fromhex(parse_params(line, parts, ['tx'])['tx']) + + def action(self, runner, line): + runner.expect_tx(self.tx, line) + + +class FundChannelEvent(object): + def __init__(self, line, parts): + d = parse_params(line, parts, ['amount', 'utxo'], ['conn']) + self.connkey = optional_connection(line, d) + self.amount = int(d['amount']) + parts = d['utxo'].partition('/') + check_hex(line, parts[0], 66) + self.utxo = (parts[0], int(parts[2])) + + def action(self, runner, line): + runner.fundchannel(which_connection(line, runner, self.connkey), + self.amount, self.utxo[0], + self.utxo[1], line) + + +class InvoiceEvent(object): + def __init__(self, line, parts): + d = parse_params(line, parts, ['amount', 'preimage']) + self.preimage = d['preimage'] + check_hex(line, self.preimage, 64) + self.amount = int(d['amount']) + + def action(self, runner, line): + runner.invoice(self.amount, self.preimage, line) + + +class ExpectErrorEvent(object): + def __init__(self, line, parts): + d = parse_params(line, parts, [], ['conn']) + self.connkey = optional_connection(line, d) + + def action(self, runner, line): + runner.expected_error = True + runner.expect_error(which_connection(line, runner, self.connkey), line) + + +class Event(object): + def __init__(self, args, desc, line): + self.args = args + self.line = copy(line) + + parts = desc.split() + self.event = parts[0] + + if parts[0] == 'connect:': + self.actor = ConnectEvent(line, parts[1:]) + elif parts[0] == 'disconnect:': + self.actor = DisconnectEvent(line, parts[1:]) + elif parts[0] == 'recv:': + self.actor = RecvEvent(line, parts[1:]) + elif parts[0] == 'expect-send:': + self.actor = ExpectSendEvent(line, parts[1:]) + elif parts[0] == 'maybe-send:': + self.actor = ExpectSendEvent(line, parts[1:], maybe=True) + elif parts[0] == 'must-not-send:': + self.actor = ExpectSendEvent(line, parts[1:], mustnot=True) + elif parts[0] == 'block:': + self.actor = BlockEvent(line, parts[1:]) + elif parts[0] == 'expect-tx:': + self.actor = ExpectTxEvent(line, parts[1:]) + elif parts[0] == 'fundchannel:': + self.actor = FundChannelEvent(line, parts[1:]) + elif parts[0] == 'invoice:': + self.actor = InvoiceEvent(line, parts[1:]) + elif parts[0] == 'expect-error:': + self.actor = ExpectErrorEvent(line, parts[1:]) + elif parts[0] == 'nothing': + self.actor = NothingEvent(line, parts[1:]) + else: + raise LineError(line, "Unknown event type {}".format(parts[0])) + + def __repr__(self): + return "Event({}, {})".format(self.event, str(self.line)) + + def flatten(self, number, stopline, prefix=''): + # Nothing doesn't even need outputting + if type(self.actor) == NothingEvent: + return False, number + return self.line.flatten(number, stopline, prefix) + + def num_steps(self): + return 1 + + def act(self, runner): + if self.args.verbose: + print("# running {}".format(self)) + self.actor.action(runner, self.line) + + +class Sequence(object): + """Ordered sequence of Events""" + def __init__(self, args): + self.args = args + self.events = [] + self.line = None + + def add_event(self, e): + self.events.append(e) + if self.line is None: + self.line = copy(e.line) + else: + self.line += e.line + + def flatten(self, number, stopline, prefix=''): + stop = False + for e in self.events: + stop, number = e.flatten(number, stopline, prefix) + if stop: + break + return stop, number + + def num_steps(self): + return sum([e.num_steps() for e in self.events]) + + def __str__(self): + return "{}".format(self.line) + + def __repr__(self): + return "Sequence:{}".format(self) + + def run(self, runner, start=0): + if self.args.verbose: + print("# running {}:".format(self)) + for e in self.events[start:]: + e.act(runner) + + +def match_which_sequence(msg, sequences): + """Return which sequence starts with expect-msg: msg, or None""" + for s in sequences: + failreason = message_match(s.events[0].actor.expectmsg, + s.events[0].actor.expectfields, msg) + if failreason is None: + return s + + return None + + +class OneOfEvent(object): + """Event representing multiple possible sequences""" + def __init__(self, args, line): + self.line = line + self.args = args + self.sequences = [] + + def __str__(self): + return str(self.line) + + def flatten(self, number, stopline, prefix): + # FIXME: if stopline is in here, we ignore it + _, number = self.line.flatten(number, stopline, prefix) + i = 1 + for s in self.sequences: + _, i = s.flatten(i, stopline, ' ') + return False, number + + def num_steps(self): + # Use the mean of the separate sequences as a guesstimate. + return sum([s.num_steps() for s in self.sequences]) / len(self.sequences) + + def add_sequence(self, seq): + actor = seq.events[0].actor + if type(actor) != ExpectSendEvent: + # We could relax this a bit if necessary, eg 'expect-error' or + # 'expect-tx' would be possible. + raise LineError(seq.events[0].line, + "First sequence event in One Of must be expect-send") + # They have to match on what conn the specify, too. + if len(self.sequences) != 0: + if actor.connkey != self.connkey: + raise LineError(seq.events[0].line, + "All first sequence event in One Of must same conn=") + else: + self.connkey = actor.connkey + self.sequences.append(seq) + + def act(self, runner): + if self.args.verbose: + print("# running {}".format(self)) + + # For DummyRunner, we assume the first. + if type(runner) == DummyRunner: + return self.sequences[0].run(runner) + + conn = which_connection(self.line, runner, self.connkey) + while True: + msg = runner.expect_send(conn, self.line) + s = match_which_sequence(msg, self.sequences) + if s is not None: + # We found the sequence, run the rest of it. + s.run(runner, start=1) + return + + if maybesend_match(conn, msg): + continue + + raise ValidationError(self.line, + "None of the sequences matched {}" + .format(msg.hex())) + + +class AnyOrderEvent(object): + """Event representing sequences in any order""" + def __init__(self, args, line): + self.line = line + self.args = args + self.sequences = [] + + def __str__(self): + return str(self.line) + + def flatten(self, number, stopline, prefix): + # FIXME: if stopline is in here, we ignore it + _, number = self.line.flatten(number, stopline, prefix) + i = 1 + for s in self.sequences: + _, i = s.flatten(i, stopline, ' ') + return False, number + + def num_steps(self): + return sum([s.num_steps() for s in self.sequences]) + + def add_sequence(self, seq): + actor = seq.events[0].actor + if type(actor) != ExpectSendEvent: + # We could relax this a bit if necessary, eg 'expect-error' or + # 'expect-tx' would be possible. + raise LineError(seq.events[0].line, + "First sequence event in Any Order must be expect-send") + # They have to match on what conn the specify, too. + if len(self.sequences) != 0: + if actor.connkey != self.connkey: + raise LineError(seq.events[0].line, + "All first sequence event in Any Order must same conn=") + else: + self.connkey = actor.connkey + self.sequences.append(seq) + + def act(self, runner): + if self.args.verbose: + print("# running {}".format(self)) + + # For DummyRunner, we assume the first. + if type(runner) == DummyRunner: + return self.sequences[0].run(runner) + + conn = which_connection(self.line, runner, self.connkey) + sequences = self.sequences[:] + while sequences != []: + msg = runner.expect_send(conn, self.line) + s = match_which_sequence(msg, sequences) + + if s is not None: + sequences.remove(s) + s.run(runner, start=1) + elif not maybesend_match(conn, msg): + raise ValidationError(self.line, + "None of the sequences matched {}" + .format(msg.hex())) + + +# Loads a Sequence at this indent level (and any children embedded in +# it, if allow_children). Returns the initial Sequence, a list of +# Sequence leaves, and the next linenum. +def load_sequence(args, lines, linenum, indentlevel, graph): + count = 1 + init_seq = Sequence(args) + + seq = init_seq + terminals = [seq] + + if graph is not None: + graph.add_node(seq) + + # We always parse one child. + if lines[linenum].indentlevel != indentlevel: + raise LineError(lines[linenum], "Expected {} indents.", indentlevel) + if not lines[linenum].line.startswith('1.'): + raise LineError(lines[linenum], "Expected 1.") + + while linenum < len(lines): + # Unindent? We're done. + if lines[linenum].indentlevel < indentlevel: + return init_seq, terminals, linenum + + # Indent? Parse children. + if lines[linenum].indentlevel == indentlevel + 1: + if graph is None: + raise LineError(lines[linenum], + "Cannot have indentations inside 'One of'/'Any order'") + child, childterms, linenum = load_sequence(args, + lines, linenum, + indentlevel + 1, graph) + + # Attach this child to our current seq. + if args.verbose: + print("# child {} -> {}".format(seq, child)) + + graph.add_edge(seq, child) + + # Seq is no longer terminal + if seq in terminals: + terminals.remove(seq) + + # These will bet attached onto the next sequence. + terminals += childterms + continue + elif lines[linenum].indentlevel != indentlevel: + raise LineError(lines[linenum], "Unexpected indent.") + + # Same level. + parts = lines[linenum].line.partition('.') + if parts[1] != '.': + raise LineError(lines[linenum], + "Expected '{}.' or '1.'".format(count)) + + # Unexpected 1. means a new start. + if parts[0] != str(count): + return init_seq, terminals, linenum + + if parts[2].split() == ['One', 'of:']: + event = OneOfEvent(args, lines[linenum]) + + # We expect indented sequences + linenum += 1 + while linenum < len(lines) and lines[linenum].indentlevel == indentlevel + 1: + # We don't allow sub-nodes here, so terminals will be [child] + child, _, linenum = load_sequence(args, lines, linenum, + indentlevel + 1, + None) + event.add_sequence(child) + + if event.sequences == []: + raise LineError(lines[linenum], + "Expected indented sequences after 'One of:'") + elif parts[2].split() == ['Any', 'order:']: + event = AnyOrderEvent(args, lines[linenum]) + + # We expect indented sequences + linenum += 1 + while linenum < len(lines) and lines[linenum].indentlevel == indentlevel + 1: + # We don't allow sub-nodes here, so terminals will be [child] + child, _, linenum = load_sequence(args, lines, linenum, + indentlevel + 1, + None) + event.add_sequence(child) + + if event.sequences == []: + raise LineError(lines[linenum], + "Expected indented sequences after 'Any order:'") + else: + event = Event(args, parts[2], lines[linenum]) + linenum += 1 + + # Any children from last step, start new Sequence for them to connect. + if terminals != [seq]: + seq = Sequence(args) + seq.add_event(event) + graph.add_node(seq) + for c in terminals: + if args.verbose: + print("# {} -> {}".format(c, seq)) + graph.add_edge(c, seq) + terminals = [seq] + else: + seq.add_event(event) + count += 1 + + # Any children will continue from our last event(s). + return init_seq, terminals, linenum + + +def run_test(args, path, runner): + if args.verbose: + print("## RESTART") + runner.restart() + runner.connections = [] + runner.expected_error = False + for seq in path: + seq.run(runner) + + # Make sure they didn't send any must-not-sends at the end. + for conn in runner.connections: + end_connection(runner, conn, path[-1].line) + + if not runner.expected_error: + error = runner.final_error() + if error is not None: + raise ValidationError(None, + "Unexpected error occurred: {}".format(error)) + + +def line_minus_comments(verbose, line, linenum): + """Strips any comment from a line, and trailing whitespace.""" + # Get the line. + arr = line.rstrip().partition('#') + if arr[1] == '#' and verbose: + if arr[2] != '': + print("# {}: {}".format(linenum, arr[2])) + return arr[0].rstrip() + + +def filter_out(args, line, filename, linenum): + """Trim options: we discard the line if it doesn't qualify.""" + while True: + m = re.search("(?P!?)" + "(?Popt[A-Za-z_]*)" + r"(?P(/(odd|even))?)\s*$", line) + if m is None: + return line + + if m.group('oddoreven') != '': + present = m.group('optname') + m.group('oddoreven') in args.option + else: + present = (m.group('optname') + '/odd' in args.option + or m.group('optname') + '/even' in args.option) + + # If option was specified as --option, invert must be set. + wanted = m.group('invert') != '!' + if present != wanted: + if args.verbose: + print("# Removing line {}: requires {}{}{}" + .format(Line(filename, linenum, linenum, 0, line), + m.group('invert'), + m.group('optname'), + m.group('oddoreven'))) + return '' + line = line[:m.start()] + + +def indentation(s): + """Returns str with indent stripped, and effective indentation amount""" + level = 0 + consumed = 0 + for i in range(len(s)): + if s[i] == ' ': + level += 1 + elif s[i] == '\t': + # I keep puttiing in tabs by mistake. Make them got to next 8. + level = (level + 8) // 8 * 8 + else: + break + consumed = i + 1 + return s[consumed:], level + + +def parse_file(args, f, filename, variables): + """Get non-comment lines, as [(linenums,indentlevel,line)], grab vars""" + content = [] + lines = f.readlines() + i = 0 + while i < len(lines): + line_start = i + + line = line_minus_comments(args.verbose, lines[i], line_start) + line = filter_out(args, line, filename, line_start) + if line == '': + i += 1 + continue + + # Store indentation level, remove it. + line, indent = indentation(line) + if indent % 4 != 0: + raise LineError(Line(filename, line_start, line_start, 0, line), + "Indent is not a multiple of 4!") + indentlevel = indent // 4 + + i += 1 + line_end = line_start + + # Grab any continuation lines + while i < len(lines): + lookahead = line_minus_comments(False, lines[i], i) + if lookahead == '': + i += 1 + continue + lookahead, indent = indentation(lookahead) + # Line continuations are non-4 indent, but must be greater. + if indent % 4 == 0: + break + if indent < indentlevel * 4: + raise LineError(Line(filename, i, i, indentlevel, lines[i]), + "Indent is not a multiple of 4!") + line += ' ' + filter_out(args, lookahead, filename, i) + line_end = i + i += 1 + + # Expand variables. + while True: + m = re.search(r"\$(?P[A-Za-z_0-9]+)", line) + if m is None: + break + + if not m.group('varname') in variables: + raise LineError(Line(filename, i, i, indentlevel, lines[i]), + "Unknown variable {}".format(m.group('varname'))) + + line = (line[:m.start()] + + variables[m.group('varname')] + + line[m.end():]) + + # Check if we're merely setting a variable; we do this now so + # we can expand inside parse_file itself. + parts = line.partition('=') + if parts[1] == '=' and re.fullmatch('[A-Za-z0-9_]+', parts[0]): + if parts[0] in variables: + raise LineError(Line(filename, line_start, line_end, + indentlevel, lines[i]), + "Re-setting var {}".format(parts[0])) + variables[parts[0]] = parts[2] + # Similarly, do include directives immediately. + elif line.startswith('include '): + # Filenames are assumed to be relative. + subfilename = path.join(path.dirname(filename), line[8:]) + subf = open(subfilename) + # This can set, and use, variables. + sublines, variables = parse_file(args, subf, subfilename, variables) + # Indent entire file as per this include line. + for l in sublines: + l.indentlevel += indentlevel + content += sublines + else: + content.append(Line(filename, line_start, line_end, indentlevel, + line)) + + return content, variables + + +def main(args, runner): + read_csv(args) + if args.verbose: + print("# loaded {} message types".format(len(messages))) + + lines = [] + for filename in args.input: + if filename is None: + filename = '' + f = sys.stdin + else: + f = open(filename) + + lines, _ = parse_file(args, f, filename, {}) + f.close() + + graph = nx.DiGraph() + root, terminals, linenum = load_sequence(args, lines, 0, 0, graph) + + # We only support one root sequence for now. + if linenum != len(lines): + raise LineError(lines[linenum], + "Unexpected lines after end of first sequence") + + if args.draw_events: + labels = {} + for seq in graph.nodes(): + labels[seq] = str(seq) + + nx.draw_circular(graph, labels=labels, node_size=50, font_size=4) + plt.savefig(filename + ".png", dpi=300) + + # Edge weight == ops in sequence it leads to. Since we walk + # most-expensive-first, this gives maximum testing coverage to + # first run. + for e in graph.edges(): + graph.edges[e]['weight'] = e[1].num_steps() + + # Get all paths + paths = [] + if args.via: + parts = args.via.partition(':') + if parts[1] == ':': + filename = parts[0] + linenum = int(parts[2]) + else: + filename = None + linenum = int(parts[0]) + via = None + for seq in graph.nodes(): + if filename and seq.line.filename != filename: + continue + if linenum < seq.line.linestart: + continue + if linenum > seq.line.lineend: + continue + via = seq + break + + if not via: + raise ValueError("{} not found".format(args.destination)) + + path1 = nx.shortest_path(graph, root, via, 'weight') + + # Now get to any terminal. + for t in terminals: + try: + path2 = nx.shortest_path(graph, via, t, 'weight') + break + except nx.exception.NetworkXNoPath: + pass + paths = [path1 + path2] + elif args.exhaustive: + # This does the simple ones first, which is usually what + # you want. + for t in terminals: + paths += nx.shortest_simple_paths(graph, root, t, 'weight') + else: + while any([graph.edges[e]['weight'] != 0 for e in graph.edges()]): + for t in terminals: + # Start with "longest" first. This is a super slow way + # to calc this! + path = list(nx.shortest_simple_paths(graph, root, t, 'weight'))[-1] + new_edge = False + for e in nx.utils.misc.pairwise(path): + if graph.edges[e]['weight'] > 0: + new_edge = True + graph.edges[e]['weight'] = 0 + + if new_edge: + if args.verbose: + print("PATH: {}".format(path)) + paths.append(path) + break + + # Special case of a single sequence + if graph.number_of_nodes() == 1: + paths = [[root]] + + if not args.verbose: + print("{}:{} paths: ".format(filename, len(paths)), end='', flush=True) + for path in paths: + try: + run_test(args, path, runner) + except ValidationError as v: + print("ERROR during {}".format([p.line for p in path]), file=sys.stderr) + if args.flatten_failpath: + index = 1 + print("FAILPATH to {}:".format(v.line)) + for p in path: + stop, index = p.flatten(index, v.line) + if stop: + break + raise + if not args.verbose: + print('.', end='', flush=True) + print("OK") + + +if __name__ == "__main__": + parser = setup_cmdline_options() + args = parser.parse_args() + + main(args, DummyRunner(args))