text: #include <bitcoin/script.h>
  #include <closingd/gen_closing_wire.h>
  #include <common/close_tx.h>
  #include <common/crypto_sync.h>
  #include <common/debug.h>
  #include <common/derive_basepoints.h>
  #include <common/htlc.h>
  #include <common/status.h>
  #include <common/type_to_string.h>
  #include <common/utils.h>
  #include <common/version.h>
  #include <errno.h>
  #include <inttypes.h>
  #include <signal.h>
  #include <stdio.h>
  #include <unistd.h>
  #include <wire/peer_wire.h>
  #include <wire/wire_sync.h>
  
  /* stdin == requests, 3 == peer, 4 = gossip */
  #define REQ_FD STDIN_FILENO
  #define PEER_FD 3
  #define GOSSIP_FD 4
  
  static struct bitcoin_tx *close_tx(const tal_t *ctx,
  				   u8 *scriptpubkey[NUM_SIDES],
  				   const struct sha256_double *funding_txid,
  				   unsigned int funding_txout,
  				   u64 funding_satoshi,
  				   const u64 satoshi_out[NUM_SIDES],
  				   enum side funder,
  				   uint64_t fee,
  				   uint64_t dust_limit)
  {
  	struct bitcoin_tx *tx;
  
  	if (satoshi_out[funder] < fee)
  		status_failed(WIRE_CLOSING_NEGOTIATION_ERROR,
  			      "Funder cannot afford fee %"PRIu64
  			      " (%"PRIu64" and %"PRIu64")",
  			      fee, satoshi_out[LOCAL],
  			      satoshi_out[REMOTE]);
  
  	status_trace("Making close tx at = %"PRIu64"/%"PRIu64" fee %"PRIu64,
  		     satoshi_out[LOCAL], satoshi_out[REMOTE], fee);
  
  	tx = create_close_tx(ctx, scriptpubkey[LOCAL], scriptpubkey[REMOTE],
  			     funding_txid,
  			     funding_txout,
  			     funding_satoshi,
  			     satoshi_out[LOCAL] - (funder == LOCAL ? fee : 0),
  			     satoshi_out[REMOTE] - (funder == REMOTE ? fee : 0),
  			     dust_limit);
  	if (!tx)
  		status_failed(WIRE_CLOSING_NEGOTIATION_ERROR,
  			      "Both outputs below dust limit:"
  			      " funding = %"PRIu64
  			      " fee = %"PRIu64
  			      " dust_limit = %"PRIu64
  			      " LOCAL = %"PRIu64
  			      " REMOTE = %"PRIu64,
  			      funding_satoshi,
  			      fee,
  			      dust_limit,
  			      satoshi_out[LOCAL],
  			      satoshi_out[REMOTE]);
  	return tx;
  }
  
  static u64 one_towards(u64 target, u64 value)
  {
  	if (value > target)
  		return value-1;
  	else if (value < target)
  		return value+1;
  	return value;
  }
  
  static void do_reconnect(struct crypto_state *cs,
  			 const struct channel_id *channel_id,
  			 const u64 next_index[NUM_SIDES],
  			 u64 revocations_received)
  {
  	u8 *msg;
  	struct channel_id their_channel_id;
  	const tal_t *tmpctx = tal_tmpctx(NULL);
  	u64 next_local_commitment_number, next_remote_revocation_number;
  
  	/* BOLT #2:
  	 *
  	 * On reconnection, a node MUST transmit `channel_reestablish` for
  	 * each channel, and MUST wait for to receive the other node's
  	 * `channel_reestablish` message before sending any other messages for
  	 * that channel.  The sending node MUST set
  	 * `next_local_commitment_number` to the commitment number of the next
  	 * `commitment_signed` it expects to receive, and MUST set
  	 * `next_remote_revocation_number` to the commitment number of the
  	 * next `revoke_and_ack` message it expects to receive.
  	 */
  	msg = towire_channel_reestablish(tmpctx, channel_id,
  					 next_index[LOCAL],
  					 revocations_received);
  	if (!sync_crypto_write(cs, PEER_FD, take(msg)))
  		status_failed(WIRE_CLOSING_PEER_WRITE_FAILED,
  			      "Failed writing reestablish: %s", strerror(errno));
  
  again:
  	msg = sync_crypto_read(tmpctx, cs, PEER_FD);
  	if (!msg)
  		status_failed(WIRE_CLOSING_PEER_READ_FAILED,
  			      "Failed reading reestablish: %s", strerror(errno));
  
  	if (is_gossip_msg(msg)) {
  		if (!wire_sync_write(GOSSIP_FD, take(msg)))
  			status_failed(WIRE_CLOSING_GOSSIP_FAILED,
  				      "Writing gossip");
  		goto again;
  	}
  
  	if (!fromwire_channel_reestablish(msg, NULL, &their_channel_id,
  					  &next_local_commitment_number,
  					  &next_remote_revocation_number)) {
  		status_failed(WIRE_CLOSING_PEER_READ_FAILED,
  			      "bad reestablish msg: %s %s",
  			      wire_type_name(fromwire_peektype(msg)),
  			      tal_hex(tmpctx, msg));
  	}
  	status_trace("Got reestablish commit=%"PRIu64" revoke=%"PRIu64,
  		     next_local_commitment_number,
  		     next_remote_revocation_number);
  
  	/* FIXME: Spec says to re-xmit funding_locked here if we haven't
  	 * done any updates. */
  
  	/* BOLT #2:
  	 *
  	 * On reconnection if the node has sent a previous `closing_signed` it
  	 * MUST send another `closing_signed`
  	 */
  
  	/* Since we always transmit closing_signed immediately, if
  	 * we're reconnecting we consider ourselves to have transmitted once,
  	 * and we'll immediately do the retransmit now anyway. */
  	tal_free(tmpctx);
  }
  
  int main(int argc, char *argv[])
  {
  	struct crypto_state cs;
  	const tal_t *ctx = tal_tmpctx(NULL);
  	u8 *msg;
  	struct privkey seed;
  	struct pubkey funding_pubkey[NUM_SIDES];
  	struct sha256_double funding_txid;
  	u16 funding_txout;
  	u64 funding_satoshi, satoshi_out[NUM_SIDES];
  	u64 our_dust_limit;
  	u64 minfee, maxfee, sent_fee;
  	s64 last_received_fee = -1;
  	enum side funder;
  	u8 *scriptpubkey[NUM_SIDES], *funding_wscript;
  	struct channel_id channel_id;
  	struct secrets secrets;
  	secp256k1_ecdsa_signature sig;
  	bool reconnected;
  	u64 next_index[NUM_SIDES], revocations_received;
  
  	if (argc == 2 && streq(argv[1], "--version")) {
  		printf("%s\n", version());
  		exit(0);
  	}
  
  	subdaemon_debug(argc, argv);
  
  	/* We handle write returning errors! */
  	signal(SIGCHLD, SIG_IGN);
  	secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
  						 | SECP256K1_CONTEXT_SIGN);
  	status_setup_sync(REQ_FD);
  
  	msg = wire_sync_read(ctx, REQ_FD);
  	if (!fromwire_closing_init(ctx, msg, NULL,
  				   &cs, &seed,
  				   &funding_txid, &funding_txout,
  				   &funding_satoshi,
  				   &funding_pubkey[REMOTE],
  				   &funder,
  				   &satoshi_out[LOCAL],
  				   &satoshi_out[REMOTE],
  				   &our_dust_limit,
  				   &minfee, &maxfee, &sent_fee,
  				   &scriptpubkey[LOCAL],
  				   &scriptpubkey[REMOTE],
  				   &reconnected,
  				   &next_index[LOCAL],
  				   &next_index[REMOTE],
  				   &revocations_received)) {
  		status_failed(WIRE_CLOSING_PEER_BAD_MESSAGE,
  			      "Bad init message %s", tal_hex(ctx, msg));
  	}
  	status_trace("satoshi_out = %"PRIu64"/%"PRIu64,
  		     satoshi_out[LOCAL], satoshi_out[REMOTE]);
  	status_trace("dustlimit = %"PRIu64, our_dust_limit);
  	status_trace("fee = %"PRIu64, sent_fee);
  	derive_channel_id(&channel_id, &funding_txid, funding_txout);
  	derive_basepoints(&seed, &funding_pubkey[LOCAL], NULL,
  			  &secrets, NULL);
  
  	funding_wscript = bitcoin_redeem_2of2(ctx,
  					      &funding_pubkey[LOCAL],
  					      &funding_pubkey[REMOTE]);
  
  	if (reconnected)
  		do_reconnect(&cs, &channel_id, next_index, revocations_received);
  
  	/* BOLT #2:
  	 *
  	 * Nodes SHOULD send a `closing_signed` message after `shutdown` has
  	 * been received and no HTLCs remain in either commitment transaction.
  	 */
  
  	/* BOLT #2:
  	 *
  	 * On reconnection, ... if the node has sent a previous
  	 * `closing_signed` it MUST send another `closing_signed`, otherwise
  	 * if the node has sent a previous `shutdown` it MUST retransmit it.
  	 */
  	for (;;) {
  		const tal_t *tmpctx = tal_tmpctx(ctx);
  		struct bitcoin_tx *tx;
  		u64 received_fee, limit_fee, new_fee;
  
  		/* BOLT #2:
  		 *
  		 * The sender MUST set `signature` to the Bitcoin signature of
  		 * the close transaction as specified in [BOLT
  		 * #3](03-transactions.md#closing-transaction).
  		 */
  		tx = close_tx(tmpctx, scriptpubkey,
  			      &funding_txid,
  			      funding_txout,
  			      funding_satoshi,
  			      satoshi_out, funder, sent_fee, our_dust_limit);
  
  		/* BOLT #3:
  		 *
  		 * ## Closing Transaction
  		 *...
  		 * Each node offering a signature... MAY also eliminate its
  		 * own output.
  		 */
  		/* (We don't do this). */
  		sign_tx_input(tx, 0, NULL, funding_wscript,
  			      &secrets.funding_privkey,
  			      &funding_pubkey[LOCAL],
  			      &sig);
  
  		status_trace("sending fee offer %"PRIu64, sent_fee);
  
  		/* Now send closing offer */
  		msg = towire_closing_signed(tmpctx, &channel_id, sent_fee, &sig);
  		if (!sync_crypto_write(&cs, PEER_FD, take(msg)))
  			status_failed(WIRE_CLOSING_PEER_WRITE_FAILED,
  				      "Writing closing_signed");
  
  		/* Did we just agree with them?  If so, we're done. */
  		if (sent_fee == last_received_fee)
  			break;
  
  	again:
  		msg = sync_crypto_read(tmpctx, &cs, PEER_FD);
  		if (!msg)
  			status_failed(WIRE_CLOSING_PEER_READ_FAILED,
  				      "Reading input");
  
  		/* We don't send gossip at this stage, but we can recv it */
  		if (is_gossip_msg(msg)) {
  			if (!wire_sync_write(GOSSIP_FD, take(msg)))
  				status_failed(WIRE_CLOSING_GOSSIP_FAILED,
  					      "Writing gossip");
  			goto again;
  		}
  
  		/* BOLT #2:
  		 *
  		 * On reconnection, a node MUST ignore a redundant
  		 * `funding_locked` if it receives one.
  		 */
  		/* This should only happen if we've made no commitments, but
  		 * we don't have to check that: it's their problem. */
  		if (fromwire_peektype(msg) == WIRE_FUNDING_LOCKED) {
  			tal_free(msg);
  			goto again;
  		}
  
  		/* BOLT #2:
  		 *
  		 * ...if the node has sent a previous `shutdown` it MUST
  		 * retransmit it.
  		 */
  		if (fromwire_peektype(msg) == WIRE_SHUTDOWN) {
  			tal_free(msg);
  			goto again;
  		}
  
  		if (!fromwire_closing_signed(msg, NULL, &channel_id,
  					     &received_fee, &sig))
  			status_failed(WIRE_CLOSING_PEER_BAD_MESSAGE,
  				      "Expected closing_signed: %s",
  				      tal_hex(trc, msg));
  
  		/* BOLT #2:
  		 *
  		 * The receiver MUST check `signature` is valid for either
  		 * variant of close transaction specified in [BOLT
  		 * #3](03-transactions.md#closing-transaction), and MUST fail
  		 * the connection if it is not.
  		 */
  		tx = close_tx(tmpctx, scriptpubkey,
  			      &funding_txid,
  			      funding_txout,
  			      funding_satoshi,
  			      satoshi_out, funder, received_fee, our_dust_limit);
  
  		if (!check_tx_sig(tx, 0, NULL, funding_wscript,
  				  &funding_pubkey[REMOTE], &sig)) {
  			/* Trim it by reducing their output to minimum */
  			struct bitcoin_tx *trimmed;
  			u64 trimming_satoshi_out[NUM_SIDES];
  
  			if (funder == REMOTE)
  				trimming_satoshi_out[REMOTE] = received_fee;
  			else
  				trimming_satoshi_out[REMOTE] = 0;
  			trimming_satoshi_out[LOCAL] = satoshi_out[LOCAL];
  
  			/* BOLT #3:
  			 *
  			 * Each node offering a signature MUST subtract the
  			 * fee given by `fee_satoshis` from the output to the
  			 * funder; it MUST then remove any output below its
  			 * own `dust_limit_satoshis`, and MAY also eliminate
  			 * its own output.
  			*/
  			trimmed = close_tx(tmpctx, scriptpubkey,
  					   &funding_txid,
  					   funding_txout,
  					   funding_satoshi,
  					   trimming_satoshi_out,
  					   funder, received_fee, our_dust_limit);
  			if (!trimmed
  			    || !check_tx_sig(trimmed, 0, NULL, funding_wscript,
  					     &funding_pubkey[REMOTE], &sig)) {
  				status_failed(WIRE_CLOSING_PEER_BAD_MESSAGE,
  					      "Bad closing_signed signature for"
  					      " %s (and trimmed version %s)",
  					      type_to_string(tmpctx,
  							     struct bitcoin_tx,
  							     tx),
  					      trimmed ?
  					      type_to_string(tmpctx,
  							     struct bitcoin_tx,
  							     trimmed)
  					      : "NONE");
  			}
  			tx = trimmed;
  		}
  
  		status_trace("Received fee offer %"PRIu64, received_fee);
  
  		/* BOLT #2:
  		 *
  		 * Otherwise, the recipient MUST fail the connection if
  		 * `fee_satoshis` is greater than the base fee of the final
  		 * commitment transaction as calculated in [BOLT #3] */
  		if (received_fee > maxfee)
  			status_failed(WIRE_CLOSING_PEER_BAD_MESSAGE,
  				      "Bad closing_signed fee %"PRIu64
  				      " > %"PRIu64,
  				      received_fee, maxfee);
  
  		/* Is fee reasonable?  Tell master. */
  		if (received_fee < minfee) {
  			status_trace("Fee too low, below %"PRIu64, minfee);
  			limit_fee = minfee;
  		} else {
  			status_trace("Fee accepted.");
  			msg = towire_closing_received_signature(tmpctx,
  								&sig, tx);
  			if (!wire_sync_write(REQ_FD, take(msg)))
  				status_failed(WIRE_CLOSING_INTERNAL_ERROR,
  					      "Writing received to master: %s",
  					      strerror(errno));
  			msg = wire_sync_read(tmpctx, REQ_FD);
  			if (!fromwire_closing_received_signature_reply(msg,NULL))
  				status_failed(WIRE_CLOSING_INTERNAL_ERROR,
  					      "Bad received reply from master");
  			limit_fee = received_fee;
  		}
  
  		/* BOLT #2:
  		 *
  		 * If `fee_satoshis` is equal to its previously sent
  		 * `fee_satoshis`, the receiver SHOULD sign and broadcast the
  		 * final closing transaction and MAY close the connection.
  		 */
  		if (received_fee == sent_fee)
  			break;
  
  		/* BOLT #2:
  		 *
  		 * the recipient SHOULD fail the connection if `fee_satoshis`
  		 * is not strictly between its last-sent `fee_satoshis` and
  		 * its previously-received `fee_satoshis`, unless it has
  		 * reconnected since then. */
  		if (last_received_fee != -1) {
  			bool previous_dir = sent_fee < last_received_fee;
  			bool dir = received_fee < last_received_fee;
  			bool next_dir = sent_fee < received_fee;
  
  			/* They went away from our offer? */
  			if (dir != previous_dir)
  				status_failed(WIRE_CLOSING_NEGOTIATION_ERROR,
  					      "Their fee went %"
  					      PRIu64" to %"PRIu64
  					      " when ours was %"PRIu64,
  					      last_received_fee,
  					      received_fee,
  					      sent_fee);
  
  			/* They jumped over our offer? */
  			if (next_dir != previous_dir)
  				status_failed(WIRE_CLOSING_NEGOTIATION_ERROR,
  					      "Their fee jumped %"
  					      PRIu64" to %"PRIu64
  					      " when ours was %"PRIu64,
  					      last_received_fee,
  					      received_fee,
  					      sent_fee);
  		}
  
  		/* BOLT #2:
  		 *
  		 * ...otherwise it MUST propose a value strictly between the
  		 * received `fee_satoshis` and its previously-sent
  		 * `fee_satoshis`.
  		 */
  
  		/* We do it by bisection, with twists:
  		 * 1. Don't go outside limits, or reach them immediately:
  		 *    treat out-of-limit offers as on-limit offers.
  		 * 2. Round towards the target, otherwise we can't close
  		 *    a final 1-satoshi gap.
  		 *
  		 * Note: Overflow impossible here, since fee <= funder amount */
  		new_fee = one_towards(limit_fee, limit_fee + sent_fee) / 2;
  
  		/* If we didn't move, give up (we're ~ at min/max). */
  		if (new_fee == sent_fee)
  			status_failed(WIRE_CLOSING_NEGOTIATION_ERROR,
  				      "Final fee %"PRIu64" vs %"PRIu64
  				      " at limits %"PRIu64"-%"PRIu64,
  				      sent_fee, received_fee,
  				      minfee, maxfee);
  
  		last_received_fee = received_fee;
  		sent_fee = new_fee;
  		tal_free(tmpctx);
  	}
  
  	/* We're done! */
  	wire_sync_write(REQ_FD, take(towire_closing_complete(ctx)));
  	tal_free(ctx);
  
  	return 0;
  }
  