Ejemplo n.º 1
0
Pkt *accept_pkt_revocation(struct peer *peer, const Pkt *pkt)
{
	const UpdateRevocation *r = pkt->update_revocation;
	struct commit_info *ci = peer->remote.commit->prev;

	/* BOLT #2:
	 *
	 * The receiver of `update_revocation` MUST check that the
	 * SHA256 hash of `revocation_preimage` matches the previous commitment
	 * transaction, and MUST fail if it does not.
	 */
	if (!check_preimage(r->revocation_preimage, &ci->revocation_hash))
		return pkt_err(peer, "complete preimage incorrect");

	/* They're revoking the previous one. */
	assert(!ci->revocation_preimage);
	ci->revocation_preimage = tal(ci, struct sha256);

	proto_to_sha256(r->revocation_preimage, ci->revocation_preimage);

	// save revocation preimages in shachain
	if (!shachain_add_hash(&peer->their_preimages, 0xFFFFFFFFFFFFFFFFL - ci->commit_num, ci->revocation_preimage))
		return pkt_err(peer, "preimage not next in shachain");

	/* Save next revocation hash. */
	proto_to_sha256(r->next_revocation_hash,
			&peer->remote.next_revocation_hash);

	/* BOLT #2:
	 *
	 * The receiver of `update_revocation`... MUST add the remote
	 * unacked changes to the set of local acked changes.
	 */
	add_acked_changes(&peer->local.commit->acked_changes, ci->unacked_changes);
	apply_changeset(peer, &peer->local, OURS,
			ci->unacked_changes,
			tal_count(ci->unacked_changes));

	/* Should never examine these again. */
	ci->unacked_changes = tal_free(ci->unacked_changes);

	/* That revocation has committed them to changes in the current commitment.
	 * Any acked changes come from our commitment, so those are now committed
	 * by both of us.
	 */
	peer_both_committed_to(peer, ci->acked_changes, THEIRS);
	
	return NULL;
}
Ejemplo n.º 2
0
/* Send a preimage for the old commit tx.  The one we've just committed to is
 * in peer->local.commit. */
void queue_pkt_revocation(struct peer *peer)
{
	UpdateRevocation *u = tal(peer, UpdateRevocation);
	struct commit_info *ci;

	update_revocation__init(u);

	assert(peer->local.commit);
	ci = peer->local.commit->prev;
	assert(ci);
	assert(!ci->revocation_preimage);

	/* We have their signature on the current one, right? */
	assert(peer->local.commit->sig);

	ci->revocation_preimage = tal(ci, struct sha256);
	peer_get_revocation_preimage(peer, ci->commit_num,
				     ci->revocation_preimage);

	u->revocation_preimage = sha256_to_proto(u, ci->revocation_preimage);

	u->next_revocation_hash = sha256_to_proto(u,
						  &peer->local.next_revocation_hash);

	queue_pkt(peer, PKT__PKT_UPDATE_REVOCATION, u);

	/* BOLT #2:
	 *
	 * The node sending `update_revocation` MUST add the local unacked
	 * changes to the set of remote acked changes.
	 */
	/* Note: this means the unacked changes as of the commit we're
	 * revoking */
	add_acked_changes(&peer->remote.commit->acked_changes, ci->unacked_changes);
	apply_changeset(peer, &peer->remote, THEIRS,
			ci->unacked_changes, tal_count(ci->unacked_changes));

	if (tal_count(ci->unacked_changes))
		remote_changes_pending(peer);

	/* We should never look at this again. */
	ci->unacked_changes = tal_free(ci->unacked_changes);

	/* That revocation has committed us to changes in the current commitment.
	 * Any acked changes come from their commitment, so those are now committed
	 * by both of us.
	 */
	peer_both_committed_to(peer, ci->acked_changes, OURS);
}
Ejemplo n.º 3
0
int event_dnssec(conf_t *conf, zone_t *zone)
{
	assert(zone);

	changeset_t ch;
	int ret = changeset_init(&ch, zone->name);
	if (ret != KNOT_EOK) {
		goto done;
	}

	uint32_t refresh_at = time(NULL);
	int sign_flags = 0;

	if (zone->flags & ZONE_FORCE_RESIGN) {
		log_zone_info(zone->name, "DNSSEC, dropping previous "
		              "signatures, resigning zone");
		zone->flags &= ~ZONE_FORCE_RESIGN;
		sign_flags = ZONE_SIGN_DROP_SIGNATURES;
	} else {
		log_zone_info(zone->name, "DNSSEC, signing zone");
		sign_flags = 0;
	}

	ret = knot_dnssec_zone_sign(zone->contents, &ch, sign_flags, &refresh_at);
	if (ret != KNOT_EOK) {
		goto done;
	}

	bool zone_changed = !changeset_empty(&ch);
	if (zone_changed) {
		/* Apply change. */
		apply_ctx_t a_ctx = { { 0 } };
		apply_init_ctx(&a_ctx);

		zone_contents_t *new_contents = NULL;
		int ret = apply_changeset(&a_ctx, zone, &ch, &new_contents);
		if (ret != KNOT_EOK) {
			log_zone_error(zone->name, "DNSSEC, failed to sign zone (%s)",
				       knot_strerror(ret));
			goto done;
		}

		/* Write change to journal. */
		ret = zone_change_store(conf, zone, &ch);
		if (ret != KNOT_EOK) {
			log_zone_error(zone->name, "DNSSEC, failed to sign zone (%s)",
				       knot_strerror(ret));
			update_rollback(&a_ctx);
			update_free_zone(&new_contents);
			goto done;
		}

		/* Switch zone contents. */
		zone_contents_t *old_contents = zone_switch_contents(zone, new_contents);
		zone->flags &= ~ZONE_EXPIRED;
		synchronize_rcu();
		update_free_zone(&old_contents);

		update_cleanup(&a_ctx);
	}

	// Schedule dependent events.

	schedule_dnssec(zone, refresh_at);
	if (zone_changed) {
		zone_events_schedule(zone, ZONE_EVENT_NOTIFY, ZONE_EVENT_NOW);
		conf_val_t val = conf_zone_get(conf, C_ZONEFILE_SYNC, zone->name);
		if (conf_int(&val) == 0) {
			zone_events_schedule(zone, ZONE_EVENT_FLUSH, ZONE_EVENT_NOW);
		}
	}

done:
	changeset_clear(&ch);
	return ret;
}