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; }
/* 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); }
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; }