diff --git a/src/knot/ctl/knotc_main.c b/src/knot/ctl/knotc_main.c
index c0591599f83091aae0e67b8634a2775f35515e15..727765da825248dad6d2739fc259d5b2a846b2de 100644
--- a/src/knot/ctl/knotc_main.c
+++ b/src/knot/ctl/knotc_main.c
@@ -213,7 +213,7 @@ static int cmd_remote(const char *cmd, uint16_t rrt, int argc, char *argv[])
 				break;
 			}
 		}
-		int res = knot_pkt_put(pkt, 0, rr, NULL, KNOT_PF_FREE);
+		int res = knot_pkt_put(pkt, 0, rr, KNOT_PF_FREE);
 		if (res != KNOT_EOK) {
 			log_server_error("Couldn't create the query.\n");
 			knot_rrset_deep_free(&rr, 1, NULL);
diff --git a/src/knot/ctl/remote.c b/src/knot/ctl/remote.c
index 5e7faa1234ae1e050e809f61758e4c1d5cc2275d..ec998d34267f9921dc1df423e02963ac4f86e91d 100644
--- a/src/knot/ctl/remote.c
+++ b/src/knot/ctl/remote.c
@@ -508,7 +508,7 @@ static int remote_send_chunk(int c, knot_pkt_t *query, const char* d, uint16_t l
 	ret = remote_create_txt(rr, d, len);
 	assert(ret == KNOT_EOK);
 
-	ret = knot_pkt_put(resp, 0, rr, NULL, KNOT_PF_FREE);
+	ret = knot_pkt_put(resp, 0, rr, KNOT_PF_FREE);
 	if (ret != KNOT_EOK) {
 		knot_rrset_deep_free(&rr, 1, NULL);
 		goto failed;
diff --git a/src/knot/dnssec/nsec-chain.c b/src/knot/dnssec/nsec-chain.c
index 6874897b49b6e9e9e25afb7f067587d0797e2d8d..f048946e3dd4925e96bd2543c7c3e922d31ba202 100644
--- a/src/knot/dnssec/nsec-chain.c
+++ b/src/knot/dnssec/nsec-chain.c
@@ -650,7 +650,7 @@ int knot_nsec_changeset_remove(const knot_rrset_t *oldrr,
 
 	// extract copy of RRSIG
 	knot_rrset_t *synth_rrsigs = NULL;
-	result = knot_rrset_synth_rrsig(oldrr, rrsigs, &synth_rrsigs, NULL);
+	result = knot_rrset_synth_rrsig(rrsigs, oldrr->type, &synth_rrsigs, NULL);
 	if (result != KNOT_EOK && result != KNOT_ENOENT) {
 		return result;
 	}
diff --git a/src/knot/dnssec/zone-sign.c b/src/knot/dnssec/zone-sign.c
index 1ab84246cfc291a4e6c32e82967e70dc0d3397da..908e4abadb32517dc3e345483b5255f4348ea739 100644
--- a/src/knot/dnssec/zone-sign.c
+++ b/src/knot/dnssec/zone-sign.c
@@ -218,7 +218,8 @@ static int remove_expired_rrsigs(const knot_rrset_t *covered,
 	int result = KNOT_EOK;
 
 	knot_rrset_t *synth_rrsig = NULL;
-	result = knot_rrset_synth_rrsig(covered, rrsigs, &synth_rrsig, NULL);
+	result = knot_rrset_synth_rrsig(rrsigs, covered->type,
+	                                &synth_rrsig, NULL);
 	if (result == KNOT_ENOENT) {
 		// Nothing to remove
 		return KNOT_EOK;
@@ -357,7 +358,7 @@ static int remove_rrset_rrsigs(const knot_rrset_t *rrset,
 	assert(changeset);
 
 	knot_rrset_t *synth_rrsig = NULL;
-	int ret = knot_rrset_synth_rrsig(rrset, rrsigs, &synth_rrsig, NULL);
+	int ret = knot_rrset_synth_rrsig(rrsigs, rrset->type, &synth_rrsig, NULL);
 	if (ret == KNOT_ENOENT) {
 		// Nothing to remove
 		return KNOT_EOK;
@@ -1009,7 +1010,8 @@ static int update_dnskeys(const knot_zone_contents_t *zone,
 	}
 
 	knot_rrset_t *dnskey_rrsig = NULL;
-	result = knot_rrset_synth_rrsig(dnskeys, rrsigs, &dnskey_rrsig, NULL);
+	result = knot_rrset_synth_rrsig(rrsigs, KNOT_RRTYPE_DNSKEY,
+	                                &dnskey_rrsig, NULL);
 	if (result != KNOT_EOK && result != KNOT_ENOENT) {
 		return result;
 	}
diff --git a/src/knot/nameserver/axfr.c b/src/knot/nameserver/axfr.c
index 2213406fa6e5f877fcfabc86a8bf6751481f8547..0e6257f23a27e9b45e1bb9ae92614aa6a4be2f7c 100644
--- a/src/knot/nameserver/axfr.c
+++ b/src/knot/nameserver/axfr.c
@@ -44,7 +44,7 @@ static int put_rrsets(knot_pkt_t *pkt, knot_node_t *node, struct axfr_proc *stat
 		if (rrset[i]->type == KNOT_RRTYPE_SOA) {
 			continue;
 		}
-		ret = knot_pkt_put(pkt, 0, rrset[i], NULL, flags);
+		ret = knot_pkt_put(pkt, 0, rrset[i], flags);
 
 		/* If something failed, remember the current RR for later. */
 		if (ret != KNOT_EOK) {
@@ -130,7 +130,7 @@ int xfr_process_list(knot_pkt_t *pkt, xfr_put_cb process_item, struct query_data
 
 	/* Prepend SOA on first packet. */
 	if (xfer->npkts == 0) {
-		ret = knot_pkt_put(pkt, 0, soa_rr, NULL, KNOT_PF_NOTRUNC);
+		ret = knot_pkt_put(pkt, 0, soa_rr, KNOT_PF_NOTRUNC);
 		if (ret != KNOT_EOK) {
 			return ret;
 		}
@@ -151,7 +151,7 @@ int xfr_process_list(knot_pkt_t *pkt, xfr_put_cb process_item, struct query_data
 
 	/* Append SOA on last packet. */
 	if (ret == KNOT_EOK) {
-		ret = knot_pkt_put(pkt, 0, soa_rr, NULL, KNOT_PF_NOTRUNC);
+		ret = knot_pkt_put(pkt, 0, soa_rr, KNOT_PF_NOTRUNC);
 	}
 
 	/* Update counters. */
diff --git a/src/knot/nameserver/chaos.c b/src/knot/nameserver/chaos.c
index 63b3f820ecf19e0d0623f4abb6ab6e89be3c8171..7e0aed43a6a4a43b8d8f4d126fce0dae41e66c2d 100644
--- a/src/knot/nameserver/chaos.c
+++ b/src/knot/nameserver/chaos.c
@@ -106,7 +106,7 @@ static int answer_txt(knot_pkt_t *response)
 		return KNOT_RCODE_SERVFAIL;
 	}
 
-	int result = knot_pkt_put(response, 0, rrset, NULL, KNOT_PF_FREE);
+	int result = knot_pkt_put(response, 0, rrset, KNOT_PF_FREE);
 	if (result != KNOT_EOK) {
 		knot_rrset_deep_free(&rrset, 1, &response->mm);
 		return KNOT_RCODE_SERVFAIL;
diff --git a/src/knot/nameserver/internet.c b/src/knot/nameserver/internet.c
index d9c6805fd4f1414eaac2e604ef54bd5ef440b447..9f0bd8811069e79acfadb731e2cc62d772110bbe 100644
--- a/src/knot/nameserver/internet.c
+++ b/src/knot/nameserver/internet.c
@@ -120,9 +120,9 @@ static bool have_dnssec(struct query_data *qdata)
 }
 
 /*! \brief Put RR into packet, expand wildcards. */
-static int put_rr(knot_pkt_t *pkt, const knot_rrset_t *rr, const knot_rrset_t *sigs,
-                  uint16_t compr_hint,
-		  uint32_t flags, struct query_data *qdata)
+int ns_put_rr(knot_pkt_t *pkt, const knot_rrset_t *rr,
+              const knot_rrset_t *rrsigs, uint16_t compr_hint,
+              uint32_t flags, struct query_data *qdata)
 {
 	/* RFC3123 s.6 - empty APL is valid, ignore other empty RRs. */
 	if (knot_rrset_rr_count(rr) < 1 &&
@@ -145,12 +145,26 @@ static int put_rr(knot_pkt_t *pkt, const knot_rrset_t *rr, const knot_rrset_t *s
 		flags |= KNOT_PF_FREE;
 	}
 
-	ret = knot_pkt_put(pkt, compr_hint, rr, sigs, flags);
-	if (ret != KNOT_EOK && (flags & KNOT_PF_FREE)) {
-		knot_rrset_deep_free((knot_rrset_t **)&rr, 1, &pkt->mm);
+	ret = knot_pkt_put(pkt, compr_hint, rr, flags);
+	if (ret != KNOT_EOK) {
+		if (flags & KNOT_PF_FREE) {
+			knot_rrset_deep_free((knot_rrset_t **)&rr, 1, &pkt->mm);
+		}
+		return ret;
 	}
 
-	return ret;
+	if (rrsigs && rr->type != KNOT_RRTYPE_RRSIG) {
+		struct rrsig_info *i = mm_alloc(qdata->mm,
+		                                sizeof(struct rrsig_info));
+		if (i == NULL) {
+			return KNOT_ENOMEM;
+		}
+		i->rrsigs = rrsigs;
+		i->type = rr->type;
+		add_tail(&qdata->rrsigs, &i->n);
+	}
+
+	return KNOT_EOK;
 }
 
 /*! \brief This is a wildcard-covered or any other terminal node for QNAME.
@@ -183,7 +197,7 @@ static int put_answer(knot_pkt_t *pkt, uint16_t type, struct query_data *qdata)
 			return KNOT_ESPACE;
 		}
 		for (unsigned i = 0; i < knot_node_rrset_count(qdata->node); ++i) {
-			ret = put_rr(pkt, rrsets[i], NULL, compr_hint, 0, qdata);
+			ret = ns_put_rr(pkt, rrsets[i], NULL, compr_hint, 0, qdata);
 			if (ret != KNOT_EOK) {
 				break;
 			}
@@ -192,7 +206,7 @@ static int put_answer(knot_pkt_t *pkt, uint16_t type, struct query_data *qdata)
 	default: /* Single RRSet of given type. */
 		rrset = knot_node_get_rrset(qdata->node, type);
 		if (rrset) {
-			ret = put_rr(pkt, rrset, rrsigs, compr_hint, 0, qdata);
+			ret = ns_put_rr(pkt, rrset, rrsigs, compr_hint, 0, qdata);
 		}
 		break;
 	}
@@ -221,7 +235,8 @@ static int put_authority_ns(knot_pkt_t *pkt, struct query_data *qdata)
 	const knot_rrset_t *ns_rrset = knot_node_rrset(zone->apex, KNOT_RRTYPE_NS);
 	const knot_rrset_t *rrsigs = knot_node_rrset(zone->apex, KNOT_RRTYPE_RRSIG);
 	if (ns_rrset) {
-		return knot_pkt_put(pkt, 0, ns_rrset, rrsigs, KNOT_PF_NOTRUNC|KNOT_PF_CHECKDUP);
+		return ns_put_rr(pkt, ns_rrset, rrsigs, COMPR_HINT_NONE,
+		                 KNOT_PF_NOTRUNC|KNOT_PF_CHECKDUP, qdata);
 	} else {
 		dbg_ns("%s: no NS RRSets in this zone, fishy...\n", __func__);
 	}
@@ -229,7 +244,8 @@ static int put_authority_ns(knot_pkt_t *pkt, struct query_data *qdata)
 }
 
 /*! \brief Puts optional SOA RRSet to the Authority section of the response. */
-static int put_authority_soa(knot_pkt_t *pkt, const knot_zone_contents_t *zone)
+static int put_authority_soa(knot_pkt_t *pkt, struct query_data *qdata,
+                             const knot_zone_contents_t *zone)
 {
 	dbg_ns("%s(%p, %p)\n", __func__, pkt, zone);
 	knot_rrset_t *soa_rrset = knot_node_get_rrset(zone->apex, KNOT_RRTYPE_SOA);
@@ -251,7 +267,7 @@ static int put_authority_soa(knot_pkt_t *pkt, const knot_zone_contents_t *zone)
 		flags |= KNOT_PF_FREE;
 	}
 
-	ret = knot_pkt_put(pkt, 0, soa_rrset, rrsigs, flags);
+	ret = ns_put_rr(pkt, soa_rrset, rrsigs, COMPR_HINT_NONE, flags, qdata);
 	if (ret != KNOT_EOK && (flags & KNOT_PF_FREE)) {
 		knot_rrset_deep_free(&soa_rrset, 1, &pkt->mm);
 	}
@@ -270,7 +286,7 @@ static int put_delegation(knot_pkt_t *pkt, struct query_data *qdata)
 	/* Insert NS record. */
 	const knot_rrset_t *rrset = knot_node_rrset(qdata->node, KNOT_RRTYPE_NS);
 	const knot_rrset_t *rrsigs = knot_node_rrset(qdata->node, KNOT_RRTYPE_RRSIG);
-	return knot_pkt_put(pkt, 0, rrset, rrsigs, 0);
+	return ns_put_rr(pkt, rrset, rrsigs, COMPR_HINT_NONE, 0, qdata);
 }
 
 /*! \brief Put additional records for given RR. */
@@ -303,7 +319,7 @@ static int put_additional(knot_pkt_t *pkt, const knot_rrset_t *rr, knot_rrinfo_t
 			if (additional == NULL) {
 				continue;
 			}
-			ret = knot_pkt_put(pkt, hint, additional, NULL, flags);
+			ret = knot_pkt_put(pkt, hint, additional, flags);
 			if (ret != KNOT_EOK) {
 				break;
 			}
@@ -329,7 +345,7 @@ static int follow_cname(knot_pkt_t *pkt, uint16_t rrtype, struct query_data *qda
 
 	/* Now, try to put CNAME to answer. */
 	uint16_t rr_count_before = pkt->rrset_count;
-	ret = put_rr(pkt, cname_rr, rrsigs, 0, flags, qdata);
+	ret = ns_put_rr(pkt, cname_rr, rrsigs, 0, flags, qdata);
 	switch (ret) {
 	case KNOT_EOK:    break;
 	case KNOT_ESPACE: return TRUNC;
@@ -351,7 +367,7 @@ static int follow_cname(knot_pkt_t *pkt, uint16_t rrtype, struct query_data *qda
 			return ERROR;
 		}
 		cname_rr = dname_cname_synth(cname_rr, qdata->name, &pkt->mm);
-		ret = put_rr(pkt, cname_rr, NULL, 0, KNOT_PF_FREE, qdata);
+		ret = ns_put_rr(pkt, cname_rr, NULL, 0, KNOT_PF_FREE, qdata);
 		switch (ret) {
 		case KNOT_EOK:    break;
 		case KNOT_ESPACE: return TRUNC;
@@ -521,7 +537,7 @@ static int solve_answer_dnssec(int state, knot_pkt_t *pkt, struct query_data *qd
 	}
 
 	/* RFC4035, section 3.1 RRSIGs for RRs in ANSWER are mandatory. */
-	int ret = nsec_append_rrsigs(pkt, false);
+	int ret = nsec_append_rrsigs(pkt, qdata, false);
 	switch(ret) {
 	case KNOT_ESPACE: return TRUNC;
 	case KNOT_EOK:    return state;
@@ -542,11 +558,11 @@ static int solve_authority(int state, knot_pkt_t *pkt, struct query_data *qdata)
 	case MISS:   /* MISS, set NXDOMAIN RCODE. */
 		dbg_ns("%s: answer is NXDOMAIN\n", __func__);
 		qdata->rcode = KNOT_RCODE_NXDOMAIN;
-		ret = put_authority_soa(pkt, zone_contents);
+		ret = put_authority_soa(pkt, qdata, zone_contents);
 		break;
 	case NODATA: /* NODATA append AUTHORITY SOA. */
 		dbg_ns("%s: answer is NODATA\n", __func__);
-		ret = put_authority_soa(pkt, zone_contents);
+		ret = put_authority_soa(pkt, qdata, zone_contents);
 		break;
 	case DELEG:  /* Referral response. */
 		ret = put_delegation(pkt, qdata);
@@ -600,7 +616,7 @@ static int solve_authority_dnssec(int state, knot_pkt_t *pkt, struct query_data
 
 	/* RFC4035, section 3.1 RRSIGs for RRs in AUTHORITY are mandatory. */
 	if (ret == KNOT_EOK) {
-		ret = nsec_append_rrsigs(pkt, false);
+		ret = nsec_append_rrsigs(pkt, qdata, false);
 	}
 
 	/* Evaluate final state. */
@@ -644,7 +660,7 @@ static int solve_additional_dnssec(int state, knot_pkt_t *pkt, struct query_data
 	}
 
 	/* RFC4035, section 3.1 RRSIGs for RRs in ADDITIONAL are optional. */
-	int ret = nsec_append_rrsigs(pkt, true);
+	int ret = nsec_append_rrsigs(pkt, qdata, true);
 	switch(ret) {
 	case KNOT_ESPACE: return TRUNC;
 	case KNOT_EOK:    return state;
diff --git a/src/knot/nameserver/internet.h b/src/knot/nameserver/internet.h
index 6b897386e00467ea38b70734dce8e2a636e30071..b1ef561ad1ffb4d603018466d5fc07a2e80080a7 100644
--- a/src/knot/nameserver/internet.h
+++ b/src/knot/nameserver/internet.h
@@ -41,6 +41,22 @@ struct query_data;
  */
 int internet_answer(knot_pkt_t *resp, struct query_data *qdata);
 
+/*!
+ * \brief Puts RRSet to packet, will store its RRSIG for later use.
+ *
+ * \param pkt         Packet to store RRSet into.
+ * \param rr          RRSet to be stored.
+ * \param rrsigs      RRSIGs to be stored.
+ * \param compr_hint  Compression hint.
+ * \param flags       Flags.
+ * \param qdata       Query data structure.
+ *
+ * \return KNOT_E*
+ */
+int ns_put_rr(knot_pkt_t *pkt, const knot_rrset_t *rr,
+              const knot_rrset_t *rrsigs, uint16_t compr_hint,
+              uint32_t flags, struct query_data *qdata);
+
 /*! \brief Require given QUERY TYPE or return error code. */
 #define NS_NEED_QTYPE(qdata, qtype_want, error_rcode) \
 	if (knot_pkt_qtype((qdata)->query) != (qtype_want)) { \
diff --git a/src/knot/nameserver/ixfr.c b/src/knot/nameserver/ixfr.c
index 36d0264fa5243c419ecd124c6eaeb094eef571c6..5668df7ffe96d7b721284577331acb83a29ae17e 100644
--- a/src/knot/nameserver/ixfr.c
+++ b/src/knot/nameserver/ixfr.c
@@ -34,7 +34,7 @@ struct ixfr_proc {
 
 /*! \brief Helper macro for putting RRs into packet. */
 #define IXFR_SAFE_PUT(pkt, rr) \
-	ret = knot_pkt_put((pkt), 0, (rr), NULL, KNOT_PF_NOTRUNC); \
+	ret = knot_pkt_put((pkt), 0, (rr), KNOT_PF_NOTRUNC); \
 	if (ret != KNOT_EOK) { \
 		return ret; \
 	}
@@ -261,7 +261,7 @@ static int ixfr_answer_soa(knot_pkt_t *pkt, struct query_data *qdata)
 	/* Guaranteed to have zone contents. */
 	const knot_node_t *apex = qdata->zone->contents->apex;
 	const knot_rrset_t *soa_rr = knot_node_rrset(apex, KNOT_RRTYPE_SOA);
-	int ret = knot_pkt_put(pkt, 0, soa_rr, NULL, 0);
+	int ret = knot_pkt_put(pkt, 0, soa_rr, 0);
 	if (ret != KNOT_EOK) {
 		qdata->rcode = KNOT_RCODE_SERVFAIL;
 		return NS_PROC_FAIL;
diff --git a/src/knot/nameserver/nsec_proofs.c b/src/knot/nameserver/nsec_proofs.c
index 7c6ad964f4e0f3b3eda9aafa609906de4c82d474..a89f7deed54ba97d3c9a26e437f9b67334cee2cf 100644
--- a/src/knot/nameserver/nsec_proofs.c
+++ b/src/knot/nameserver/nsec_proofs.c
@@ -2,6 +2,7 @@
 
 #include "knot/nameserver/nsec_proofs.h"
 #include "knot/nameserver/process_query.h"
+#include "knot/nameserver/internet.h"
 #include "knot/dnssec/zone-nsec.h"
 
 #include "libknot/common.h"
@@ -56,6 +57,7 @@ static knot_dname_t *ns_next_closer(const knot_dname_t *closest_encloser,
  * \param resp Response where to add the RRSets.
  */
 static int ns_put_nsec3_from_node(const knot_node_t *node,
+                                  struct query_data *qdata,
                                   knot_pkt_t *resp)
 {
 	knot_rrset_t *rrset = knot_node_get_rrset(node, KNOT_RRTYPE_NSEC3);
@@ -67,7 +69,8 @@ static int ns_put_nsec3_from_node(const knot_node_t *node,
 
 	int res = KNOT_EOK;
 	if (knot_rrset_rr_count(rrset)) {
-		res = knot_pkt_put(resp, 0, rrset, rrsigs, KNOT_PF_CHECKDUP);
+		res = ns_put_rr(resp, rrset, rrsigs, COMPR_HINT_NONE,
+		                KNOT_PF_CHECKDUP, qdata);
 	}
 
 	/*! \note TC bit is already set, if something went wrong. */
@@ -91,6 +94,7 @@ static int ns_put_nsec3_from_node(const knot_node_t *node,
  */
 static int ns_put_covering_nsec3(const knot_zone_contents_t *zone,
                                  const knot_dname_t *name,
+                                 struct query_data *qdata,
                                  knot_pkt_t *resp)
 {
 	const knot_node_t *prev, *node;
@@ -114,7 +118,7 @@ dbg_ns_exec_verb(
 	free(name);
 );
 
-	return ns_put_nsec3_from_node(prev, resp);
+	return ns_put_nsec3_from_node(prev, qdata, resp);
 }
 
 /*----------------------------------------------------------------------------*/
@@ -141,6 +145,7 @@ static int ns_put_nsec3_closest_encloser_proof(
                                          const knot_zone_contents_t *zone,
                                          const knot_node_t **closest_encloser,
                                          const knot_dname_t *qname,
+                                         struct query_data *qdata,
                                          knot_pkt_t *resp)
 {
 	assert(zone != NULL);
@@ -203,7 +208,7 @@ dbg_ns_exec_verb(
 	}
 );
 
-	int ret = ns_put_nsec3_from_node(nsec3_node, resp);
+	int ret = ns_put_nsec3_from_node(nsec3_node, qdata, resp);
 	if (ret != KNOT_EOK) {
 		return ret;
 	}
@@ -224,11 +229,11 @@ dbg_ns_exec_verb(
 		dbg_ns_verb("Next closer name: %s\n", name);
 		free(name);
 );
-		ret = ns_put_covering_nsec3(zone, new_next_closer, resp);
+		ret = ns_put_covering_nsec3(zone, new_next_closer, qdata, resp);
 
 		knot_dname_free(&new_next_closer);
 	} else {
-		ret = ns_put_covering_nsec3(zone, next_closer, resp);
+		ret = ns_put_covering_nsec3(zone, next_closer, qdata, resp);
 	}
 
 	return ret;
@@ -279,6 +284,7 @@ dbg_ns_exec_verb(
 static int ns_put_nsec_wildcard(const knot_zone_contents_t *zone,
                                 const knot_dname_t *qname,
                                 const knot_node_t *previous,
+                                struct query_data *qdata,
                                 knot_pkt_t *resp)
 {
 	// check if we have previous; if not, find one using the tree
@@ -295,16 +301,14 @@ static int ns_put_nsec_wildcard(const knot_zone_contents_t *zone,
 		}
 	}
 
-	knot_rrset_t *rrset =
-		knot_node_get_rrset(previous, KNOT_RRTYPE_NSEC);
-	const knot_rrset_t *rrsigs =
-		knot_node_rrset(previous, KNOT_RRTYPE_RRSIG);
+	const knot_rrset_t *rrset = knot_node_rrset(previous, KNOT_RRTYPE_NSEC);
+	const knot_rrset_t *rrsigs = knot_node_rrset(previous, KNOT_RRTYPE_RRSIG);
 
 	int ret = KNOT_EOK;
 
 	if (rrset != NULL && knot_rrset_rr_count(rrset)) {
 		// NSEC proving that there is no node with the searched name
-		ret = knot_pkt_put(resp, 0, rrset, rrsigs, 0);
+		ret = ns_put_rr(resp, rrset, rrsigs, COMPR_HINT_NONE, 0, qdata);
 	}
 
 	return ret;
@@ -327,6 +331,7 @@ static int ns_put_nsec_wildcard(const knot_zone_contents_t *zone,
  */
 static int ns_put_nsec3_no_wildcard_child(const knot_zone_contents_t *zone,
                                           const knot_node_t *node,
+                                          struct query_data *qdata,
                                           knot_pkt_t *resp)
 {
 	assert(node != NULL);
@@ -338,7 +343,7 @@ static int ns_put_nsec3_no_wildcard_child(const knot_zone_contents_t *zone,
 	if (wildcard == NULL) {
 		ret = KNOT_ERROR; /* servfail */
 	} else {
-		ret = ns_put_covering_nsec3(zone, wildcard, resp);
+		ret = ns_put_covering_nsec3(zone, wildcard, qdata, resp);
 
 		/* Directly discard wildcard. */
 		knot_dname_free(&wildcard);
@@ -367,6 +372,7 @@ static int ns_put_nsec3_no_wildcard_child(const knot_zone_contents_t *zone,
 static int ns_put_nsec3_wildcard(const knot_zone_contents_t *zone,
                                  const knot_node_t *closest_encloser,
                                  const knot_dname_t *qname,
+                                 struct query_data *qdata,
                                  knot_pkt_t *resp)
 {
 	assert(closest_encloser != NULL);
@@ -393,7 +399,7 @@ dbg_ns_exec_verb(
 	dbg_ns_verb("Next closer name: %s\n", name);
 	free(name);
 );
-	int ret = ns_put_covering_nsec3(zone, next_closer, resp);
+	int ret = ns_put_covering_nsec3(zone, next_closer, qdata, resp);
 
 	/* Duplicate from ns_next_close(), safe to discard. */
 	knot_dname_free(&next_closer);
@@ -419,11 +425,12 @@ dbg_ns_exec_verb(
  * \retval NS_ERR_SERVFAIL
  */
 static int ns_put_nsec_nsec3_wildcard_answer(const knot_node_t *node,
-                                          const knot_node_t *closest_encloser,
-                                          const knot_node_t *previous,
-                                          const knot_zone_contents_t *zone,
-                                          const knot_dname_t *qname,
-                                          knot_pkt_t *resp)
+                                             const knot_node_t *closest_encloser,
+                                             const knot_node_t *previous,
+                                             const knot_zone_contents_t *zone,
+                                             const knot_dname_t *qname,
+                                             struct query_data *qdata,
+                                             knot_pkt_t *resp)
 {
 	// if wildcard answer, add NSEC / NSEC3
 
@@ -433,9 +440,10 @@ static int ns_put_nsec_nsec3_wildcard_answer(const knot_node_t *node,
 		dbg_ns_verb("Adding NSEC/NSEC3 for wildcard answer.\n");
 		if (knot_is_nsec3_enabled(zone)) {
 			ret = ns_put_nsec3_wildcard(zone, closest_encloser,
-			                            qname, resp);
+			                            qname, qdata, resp);
 		} else {
-			ret = ns_put_nsec_wildcard(zone, qname, previous, resp);
+			ret = ns_put_nsec_wildcard(zone, qname, previous, qdata,
+			                           resp);
 		}
 	}
 	return ret;
@@ -463,6 +471,7 @@ static int ns_put_nsec_nxdomain(const knot_dname_t *qname,
                                 const knot_zone_contents_t *zone,
                                 const knot_node_t *previous,
                                 const knot_node_t *closest_encloser,
+                                struct query_data *qdata,
                                 knot_pkt_t *resp)
 {
 	knot_rrset_t *rrset = NULL;
@@ -499,7 +508,7 @@ dbg_ns_exec_verb(
 
 	}
 
-	int ret = knot_pkt_put(resp, 0, rrset, rrsigs, 0);
+	int ret = ns_put_rr(resp, rrset, rrsigs, COMPR_HINT_NONE, 0, qdata);
 	if (ret != KNOT_EOK) {
 		dbg_ns("Failed to add NSEC for NXDOMAIN to response: %s\n",
 		       knot_strerror(ret));
@@ -549,7 +558,7 @@ dbg_ns_exec_verb(
 			// bad zone, ignore
 			return KNOT_EOK;
 		}
-		ret = knot_pkt_put(resp, 0, rrset, rrsigs, 0);
+		ret = ns_put_rr(resp, rrset, rrsigs, COMPR_HINT_NONE, 0, qdata);
 		if (ret != KNOT_EOK) {
 			dbg_ns("Failed to add second NSEC for NXDOMAIN to "
 			       "response: %s\n", knot_strerror(ret));
@@ -579,17 +588,18 @@ dbg_ns_exec_verb(
 static int ns_put_nsec3_nxdomain(const knot_zone_contents_t *zone,
                                  const knot_node_t *closest_encloser,
                                  const knot_dname_t *qname,
+                                 struct query_data *qdata,
                                  knot_pkt_t *resp)
 {
 	// 1) Closest encloser proof
 	int ret = ns_put_nsec3_closest_encloser_proof(zone, &closest_encloser,
-	                                              qname, resp);
+	                                              qname, qdata, resp);
 	// 2) NSEC3 covering non-existent wildcard
 	if (ret == KNOT_EOK && closest_encloser != NULL) {
 		dbg_ns_verb("Putting NSEC3 for no wildcard child of closest "
 		            "encloser.\n");
 		ret = ns_put_nsec3_no_wildcard_child(zone, closest_encloser,
-		                                     resp);
+		                                     qdata, resp);
 	}
 
 	return ret;
@@ -618,16 +628,17 @@ static int ns_put_nsec_nsec3_nxdomain(const knot_zone_contents_t *zone,
                                       const knot_node_t *previous,
                                       const knot_node_t *closest_encloser,
                                       const knot_dname_t *qname,
+                                      struct query_data *qdata,
                                       knot_pkt_t *resp)
 {
 	int ret = 0;
 
 	if (knot_is_nsec3_enabled(zone)) {
 		ret = ns_put_nsec3_nxdomain(zone, closest_encloser,
-		                            qname, resp);
+		                            qname, qdata, resp);
 	} else {
 		ret = ns_put_nsec_nxdomain(qname, zone, previous,
-		                           closest_encloser, resp);
+		                           closest_encloser, qdata, resp);
 	}
 
 	return ret;
@@ -646,17 +657,18 @@ static int ns_put_nsec_nsec3_nxdomain(const knot_zone_contents_t *zone,
  * \param resp Response where to add the NSECs or NSEC3s.
  */
 static int ns_put_nsec_nsec3_nodata(const knot_node_t *node,
-			     const knot_node_t *closest_encloser,
-			     const knot_node_t *previous,
-			     const knot_zone_contents_t *zone,
-			     const knot_dname_t *qname,
-			     knot_pkt_t *resp)
+                                    const knot_node_t *closest_encloser,
+                                    const knot_node_t *previous,
+                                    const knot_zone_contents_t *zone,
+                                    const knot_dname_t *qname,
+                                    struct query_data *qdata,
+                                    knot_pkt_t *resp)
 {
 	// This case must be handled first, before handling the wildcard case
 	if (knot_node_rrset_count(node) == 0 && !knot_is_nsec3_enabled(zone)) {
 		// node is an empty non-terminal => NSEC for NXDOMAIN
 		return ns_put_nsec_nxdomain(qname, zone, previous,
-		                            closest_encloser, resp);
+		                            closest_encloser, qdata, resp);
 	}
 
 	/*! \todo Maybe distinguish different errors. */
@@ -671,19 +683,22 @@ static int ns_put_nsec_nsec3_nodata(const knot_node_t *node,
 			dbg_ns("%s: adding NSEC3 wildcard NODATA\n", __func__);
 			ret = ns_put_nsec3_closest_encloser_proof(zone,
 			                                          &closest_encloser,
-			                                          qname, resp);
+			                                          qname, qdata,
+			                                          resp);
 		}
 
 		/* RFC5155 7.2.3-7.2.5 common proof. */
 		dbg_ns("%s: adding NSEC3 NODATA\n", __func__);
 		const knot_node_t *nsec3_node = knot_node_nsec3_node(node);
 		if (nsec3_node) {
-			ret = ns_put_nsec3_from_node(nsec3_node, resp);
+			ret = ns_put_nsec3_from_node(nsec3_node, qdata, resp);
 		} else {
 			// No NSEC3 node => Opt-out
 			return ns_put_nsec3_closest_encloser_proof(zone,
-								   &node,
-								   qname, resp);
+			                                           &node,
+			                                           qname,
+			                                           qdata,
+			                                           resp);
 
 		}
 	} else {
@@ -693,7 +708,7 @@ static int ns_put_nsec_nsec3_nodata(const knot_node_t *node,
 		    && knot_rrset_rr_count(rrset)) {
 			dbg_ns_detail("Putting the RRSet to Authority\n");
 			const knot_rrset_t *rrsigs = knot_node_rrset(node, KNOT_RRTYPE_RRSIG);
-			ret = knot_pkt_put(resp, 0, rrset, rrsigs, 0);
+			ret = ns_put_rr(resp, rrset, rrsigs, COMPR_HINT_NONE, 0, qdata);
 		}
 	}
 
@@ -716,7 +731,7 @@ int nsec_prove_wildcards(knot_pkt_t *pkt, struct query_data *qdata)
 					item->node,
 					knot_node_parent(item->node),
 					NULL, qdata->zone->contents,
-					item->sname,
+					item->sname, qdata,
 					pkt);
 		if (ret != KNOT_EOK) {
 			break;
@@ -732,7 +747,7 @@ int nsec_prove_nodata(knot_pkt_t *pkt, struct query_data *qdata)
 
 	return ns_put_nsec_nsec3_nodata(qdata->node, qdata->encloser,
 	                                qdata->previous, qdata->zone->contents,
-	                                qdata->name, pkt);
+	                                qdata->name, qdata, pkt);
 }
 
 int nsec_prove_nxdomain(knot_pkt_t *pkt, struct query_data *qdata)
@@ -740,7 +755,7 @@ int nsec_prove_nxdomain(knot_pkt_t *pkt, struct query_data *qdata)
 	dbg_ns("%s(%p, %p)\n", __func__, pkt, qdata);
 
 	return ns_put_nsec_nsec3_nxdomain(qdata->zone->contents, qdata->previous,
-	                                  qdata->encloser, qdata->name,
+	                                  qdata->encloser, qdata->name, qdata,
 	                                  pkt);
 }
 
@@ -752,7 +767,7 @@ int nsec_prove_dp_security(knot_pkt_t *pkt, struct query_data *qdata)
 	knot_rrset_t *rrset = knot_node_get_rrset(qdata->node, KNOT_RRTYPE_DS);
 	const knot_rrset_t *rrsigs = knot_node_get_rrset(qdata->node, KNOT_RRTYPE_RRSIG);
 	if (rrset != NULL) {
-		return knot_pkt_put(pkt, 0, rrset, rrsigs, 0);
+		return ns_put_rr(pkt, rrset, rrsigs, COMPR_HINT_NONE, 0, qdata);
 	}
 
 	/* DS doesn't exist => NODATA proof. */
@@ -760,10 +775,10 @@ int nsec_prove_dp_security(knot_pkt_t *pkt, struct query_data *qdata)
 	                                qdata->encloser,
 	                                qdata->previous,
 	                                qdata->zone->contents,
-	                                qdata->name, pkt);
+	                                qdata->name, qdata, pkt);
 }
 
-int nsec_append_rrsigs(knot_pkt_t *pkt, bool optional)
+int nsec_append_rrsigs(knot_pkt_t *pkt, struct query_data *qdata, bool optional)
 {
 	dbg_ns("%s(%p, optional=%d)\n", __func__, pkt, optional);
 
@@ -771,26 +786,31 @@ int nsec_append_rrsigs(knot_pkt_t *pkt, bool optional)
 	uint32_t flags = (optional) ? KNOT_PF_NOTRUNC : KNOT_PF_NULL;
 	flags |= KNOT_PF_FREE; // Free all RRSIGs, they are synthesized
 	uint16_t compr_hint = COMPR_HINT_NONE;
-	const knot_rrset_t *rr = NULL;
-	const knot_pktsection_t *section = knot_pkt_section(pkt, pkt->current);
-
-	/* Append RRSIG for each RR in given section. */
-	for (uint16_t i = 0; i < section->count; ++i) {
-		rr = section->rr[i];
-		compr_hint = section->rrinfo[i].compress_ptr[0];
-		if (section->rrinfo[i].rrsigs) {
-			knot_rrset_t *synth_sig = NULL;
-			ret = knot_rrset_synth_rrsig(rr, section->rrinfo[i].rrsigs, &synth_sig, &pkt->mm);
-			if (ret != KNOT_EOK && ret != KNOT_ENOENT) {
-				break;
-			}
-			ret = knot_pkt_put(pkt, compr_hint, synth_sig, NULL, flags);
-			if (ret != KNOT_EOK) {
-				knot_rrset_deep_free(&synth_sig, 1, &pkt->mm);
-				break;
+
+	/* Append RRSIGs for section. */
+	node_t *n = NULL, *nxt = NULL;
+	WALK_LIST_DELSAFE(n, nxt, qdata->rrsigs) {
+		struct rrsig_info *info = (struct rrsig_info *)n;
+		rem_node(n);
+		const knot_rrset_t *rrsigs = info->rrsigs;
+		const uint16_t covered_type = info->type;
+		mm_free(qdata->mm, info);
+		knot_rrset_t *synth_sig = NULL;
+		ret = knot_rrset_synth_rrsig(rrsigs, covered_type,
+		                             &synth_sig, &pkt->mm);
+		if (ret != KNOT_EOK) {
+			if (ret != KNOT_ENOENT) {
+				return ret;
 			}
 		}
-	}
+		ret = knot_pkt_put(pkt, compr_hint, synth_sig, flags);
+		if (ret != KNOT_EOK) {
+			knot_rrset_deep_free(&synth_sig, 1, &pkt->mm);
+			return ret;
+		}
+	};
 
-	return ret;
+	assert(EMPTY_LIST(qdata->rrsigs));
+
+	return KNOT_EOK;
 }
diff --git a/src/knot/nameserver/nsec_proofs.h b/src/knot/nameserver/nsec_proofs.h
index e8b1ad18de29a2cc787b7372f762a01520712f0f..59d18b0e19de95c97371c3867bc6eca0e4e01d34 100644
--- a/src/knot/nameserver/nsec_proofs.h
+++ b/src/knot/nameserver/nsec_proofs.h
@@ -46,7 +46,7 @@ int nsec_prove_nodata(knot_pkt_t *pkt, struct query_data *qdata);
 int nsec_prove_dp_security(knot_pkt_t *pkt, struct query_data *qdata);
 
 /*! \brief Append missing RRSIGs for current processing section. */
-int nsec_append_rrsigs(knot_pkt_t *pkt, bool optional);
+int nsec_append_rrsigs(knot_pkt_t *pkt, struct query_data *qdata, bool optional);
 
 #endif /* _KNOT_NSEC_PROOFS_H_ */
 
diff --git a/src/knot/nameserver/process_query.c b/src/knot/nameserver/process_query.c
index 047d63cd0aa021495dd005b8414b306e944b3b66..8d8bb02b677261e87eb6ec06aadaed1227d3e486 100644
--- a/src/knot/nameserver/process_query.c
+++ b/src/knot/nameserver/process_query.c
@@ -50,8 +50,9 @@ static void query_data_init(knot_process_t *ctx, void *module_param)
 	data->mm = &ctx->mm;
 	data->param = (struct process_query_param*)module_param;
 
-	/* Initialize list. */
+	/* Initialize lists. */
 	init_list(&data->wildcards);
+	init_list(&data->rrsigs);
 }
 
 int process_query_begin(knot_process_t *ctx, void *module_param)
@@ -79,6 +80,7 @@ int process_query_reset(knot_process_t *ctx)
 	/* Free allocated data. */
 	knot_pkt_free(&qdata->query);
 	ptrlist_free(&qdata->wildcards, qdata->mm);
+	ptrlist_free(&qdata->rrsigs, qdata->mm);
 	if (qdata->ext_cleanup != NULL) {
 		qdata->ext_cleanup(qdata);
 	}
diff --git a/src/knot/nameserver/process_query.h b/src/knot/nameserver/process_query.h
index f2981de421a62f5434c1ed896f87f4c1b3e7c3c3..66c320279abdf01cf66af7217c3a1d9d6a7d3e74 100644
--- a/src/knot/nameserver/process_query.h
+++ b/src/knot/nameserver/process_query.h
@@ -79,6 +79,7 @@ struct query_data {
 	knot_pkt_t *query;    /*!< Query to be solved. */
 	const zone_t *zone;   /*!< Zone from which is answered. */
 	list_t wildcards;     /*!< Visited wildcards. */
+	list_t rrsigs;        /*!< Section RRSIGs. */
 
 	/* Current processed name and nodes. */
 	const knot_node_t *node, *encloser, *previous;
@@ -104,6 +105,13 @@ struct wildcard_hit {
 	const knot_dname_t *sname; /* Name leading to this node. */
 };
 
+/*! \brief RRSIGs info. */
+struct rrsig_info {
+	node_t n;
+	const knot_rrset_t *rrsigs;   /* RRSIGs for node. */
+	uint16_t type;                /* Covered type. */
+};
+
 /*!
  * \brief Initialize query processing context.
  *
diff --git a/src/knot/updates/xfr-in.c b/src/knot/updates/xfr-in.c
index 78bdb2f9f72eddef7c21b87af67b193dc05f027a..0ff25c4af02fb3b2dcb09d319b44b5f9bd55c28d 100644
--- a/src/knot/updates/xfr-in.c
+++ b/src/knot/updates/xfr-in.c
@@ -134,7 +134,7 @@ int xfrin_create_ixfr_query(const zone_t *zone, knot_pkt_t *pkt)
 	knot_node_t *apex = zone->contents->apex;
 	const knot_rrset_t *soa = knot_node_rrset(apex, KNOT_RRTYPE_SOA);
 	knot_pkt_begin(pkt, KNOT_AUTHORITY);
-	return knot_pkt_put(pkt, COMPR_HINT_QNAME, soa, NULL, 0);
+	return knot_pkt_put(pkt, COMPR_HINT_QNAME, soa, 0);
 }
 
 /*----------------------------------------------------------------------------*/
diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c
index fff610e05ef6a530d062133ab513862590800316..9ff3f0788a8bd38a72f7d6b72622bcbb326aa4e4 100644
--- a/src/knot/zone/semantic-check.c
+++ b/src/knot/zone/semantic-check.c
@@ -439,8 +439,8 @@ static int check_rrsig_in_rrset(err_handler_t *handler,
 		return KNOT_ENOMEM;
 	}
 	knot_rrset_t *rrsigs = NULL;
-	ret = knot_rrset_synth_rrsig(rrset,
-	                             knot_node_rrset(node, KNOT_RRTYPE_RRSIG),
+	ret = knot_rrset_synth_rrsig(knot_node_rrset(node, KNOT_RRTYPE_RRSIG),
+	                             rrset->type,
 	                             &rrsigs, NULL);
 	if (ret != KNOT_EOK && ret != KNOT_ENOENT) {
 		return ret;
diff --git a/src/libknot/dnssec/rrset-sign.c b/src/libknot/dnssec/rrset-sign.c
index a22cc4f1ac13f62597cb95c2fe49a234fb006d86..5e9184a37c7cc73db5d6756421a149070e8d9d55 100644
--- a/src/libknot/dnssec/rrset-sign.c
+++ b/src/libknot/dnssec/rrset-sign.c
@@ -361,7 +361,8 @@ int knot_is_valid_signature(const knot_rrset_t *covered,
 
 	// Synthesize RRSIG for covered RRSet
 	knot_rrset_t *synth_rrsigs = NULL;
-	int result = knot_rrset_synth_rrsig(covered, rrsigs, &synth_rrsigs, NULL);
+	int result = knot_rrset_synth_rrsig(rrsigs, covered->type,
+	                                    &synth_rrsigs, NULL);
 	if (result != KNOT_EOK) {
 		return result;
 	}
diff --git a/src/libknot/packet/compr.h b/src/libknot/packet/compr.h
index 4883ea63edee32a962c30116fbdc3400be93feec..54a555fa6f298a330c3c8985812a9463559cdc82 100644
--- a/src/libknot/packet/compr.h
+++ b/src/libknot/packet/compr.h
@@ -63,7 +63,6 @@ typedef struct {
 	uint16_t pos;   /* RRSet position in the packet. */
 	uint16_t flags; /* RRSet flags. */
 	uint16_t compress_ptr[COMPR_HINT_COUNT]; /* Array of compr. ptr hints. */
-	const knot_rrset_t *rrsigs; /* Optional: RRSet containing RRSet's RRSIGs. */
 } knot_rrinfo_t;
 
 /*!
diff --git a/src/libknot/packet/pkt.c b/src/libknot/packet/pkt.c
index a8dd73c83bccad7e59b92f6bb3a97c8eb185df62..d10512e9a07fc9d6a8cd512295a57270ae02baae 100644
--- a/src/libknot/packet/pkt.c
+++ b/src/libknot/packet/pkt.c
@@ -495,7 +495,7 @@ int knot_pkt_put_opt(knot_pkt_t *pkt)
 	return KNOT_EOK;
 }
 
-int knot_pkt_put(knot_pkt_t *pkt, uint16_t compr_hint, const knot_rrset_t *rr, const knot_rrset_t *rrsigs, uint16_t flags)
+int knot_pkt_put(knot_pkt_t *pkt, uint16_t compr_hint, const knot_rrset_t *rr, uint16_t flags)
 {
 	dbg_packet("%s(%p, %u, %p, %u)\n", __func__, pkt, compr_hint, rr, flags);
 	if (pkt == NULL || rr == NULL) {
@@ -507,7 +507,6 @@ int knot_pkt_put(knot_pkt_t *pkt, uint16_t compr_hint, const knot_rrset_t *rr, c
 	rrinfo->pos = pkt->size;
 	rrinfo->flags = flags;
 	rrinfo->compress_ptr[0] = compr_hint;
-	rrinfo->rrsigs = rr->type != KNOT_RRTYPE_RRSIG ? rrsigs : NULL;
 	pkt->rr[pkt->rrset_count] = rr;
 
 	/* Check for double insertion. */
diff --git a/src/libknot/packet/pkt.h b/src/libknot/packet/pkt.h
index 6b8e0e82f241e5a6479b9e43a6ccd833d063ddfe..56113adb41e54f7969fadd8456f5451726119cb0 100644
--- a/src/libknot/packet/pkt.h
+++ b/src/libknot/packet/pkt.h
@@ -227,11 +227,10 @@ int knot_pkt_put_opt(knot_pkt_t *pkt);
  * \param pkt
  * \param compr_hint Compression hint, see enum knot_compr_hint or absolute position.
  * \param rr Given RRSet.
- * \param rrsigs RRSIGs of all RRs in node (optional).
  * \param flags RRSet flags (set PF_FREE if you want RRSet to be freed with the packet).
  * \return KNOT_EOK, KNOT_ESPACE, various errors
  */
-int knot_pkt_put(knot_pkt_t *pkt, uint16_t compr_hint, const knot_rrset_t *rr, const knot_rrset_t *sig, uint16_t flags);
+int knot_pkt_put(knot_pkt_t *pkt, uint16_t compr_hint, const knot_rrset_t *rr, uint16_t flags);
 
 /*! \brief Get description of the given packet section. */
 const knot_pktsection_t *knot_pkt_section(const knot_pkt_t *pkt, knot_section_t section_id);
diff --git a/src/libknot/rrset.c b/src/libknot/rrset.c
index 69afd9ca3b6f861423958c68031c5ecf94706f01..0b181a576eaf191c3d02fcff0f5d98421a10e8d2 100644
--- a/src/libknot/rrset.c
+++ b/src/libknot/rrset.c
@@ -1590,14 +1590,14 @@ static int add_rdata_to_rrsig(knot_rrset_t *new_sig, uint16_t type,
 	return knot_rrset_rr_count(new_sig) > 0 ? KNOT_EOK : KNOT_ENOENT;
 }
 
-int knot_rrset_synth_rrsig(const knot_rrset_t *covered, const knot_rrset_t *rrsigs,
+int knot_rrset_synth_rrsig(const knot_rrset_t *rrsigs, uint16_t type,
                            knot_rrset_t **out_sig, mm_ctx_t *mm)
 {
-	if (covered == NULL || rrsigs == NULL) {
+	if (rrsigs == NULL) {
 		return KNOT_ENOENT;
 	}
 
-	if (out_sig == NULL || !knot_dname_is_equal(covered->owner, rrsigs->owner)) {
+	if (out_sig == NULL) {
 		return KNOT_EINVAL;
 	}
 
@@ -1606,7 +1606,7 @@ int knot_rrset_synth_rrsig(const knot_rrset_t *covered, const knot_rrset_t *rrsi
 		return KNOT_ENOMEM;
 	}
 
-	int ret = add_rdata_to_rrsig(*out_sig, covered->type, rrsigs, mm);
+	int ret = add_rdata_to_rrsig(*out_sig, type, rrsigs, mm);
 	if (ret != KNOT_EOK) {
 		knot_rrset_deep_free(out_sig, 1, mm);
 		return ret;
diff --git a/src/libknot/rrset.h b/src/libknot/rrset.h
index 81e3e49ee62a3bc6b7cae05f13d7a483d726c17e..6a80e74e3e16b5d3e122a2f0042b70a867b2bcc4 100644
--- a/src/libknot/rrset.h
+++ b/src/libknot/rrset.h
@@ -387,15 +387,14 @@ int rrset_additional_needed(uint16_t rrtype);
 /*!
  * \brief Creates RRSIG record from node RRSIGs for given RRSet.
  *
- * \param covered  RRSet to create RRSIG for.
  * \param rrsigs   Node RRSIGs.
+ * \param type     Type to cover.
  * \param out_sig  Output RRSIG.
  * \param mm       Memory context.
  *
  * \return KNOT_E*
  */
-int knot_rrset_synth_rrsig(const knot_rrset_t *covered,
-                           const knot_rrset_t *rrsigs, knot_rrset_t **out_sig,
+int knot_rrset_synth_rrsig(const knot_rrset_t *rrsigs, uint16_t type, knot_rrset_t **out_sig,
                            mm_ctx_t *mm);
 
 size_t knot_rrset_rr_count(const knot_rrset_t *rrset);
diff --git a/src/utils/dig/dig_exec.c b/src/utils/dig/dig_exec.c
index 24005fa6230efa7048ea6bc54e534fdc03ec1e17..9b24091032d9cf31ce114a65af28f2128ade5d19 100644
--- a/src/utils/dig/dig_exec.c
+++ b/src/utils/dig/dig_exec.c
@@ -130,7 +130,7 @@ static knot_pkt_t* create_query_packet(const query_t *query)
 
 		// Add authority section.
 		knot_pkt_begin(packet, KNOT_AUTHORITY);
-		ret = knot_pkt_put(packet, 0, soa, NULL, KNOT_PF_FREE);
+		ret = knot_pkt_put(packet, 0, soa, KNOT_PF_FREE);
 		if (ret != KNOT_EOK) {
 			knot_rrset_deep_free(&soa, 1, &packet->mm);
 			knot_pkt_free(&packet);
diff --git a/src/utils/nsupdate/nsupdate_exec.c b/src/utils/nsupdate/nsupdate_exec.c
index 159cc82b098b42e1fb38656e4d437c403a878744..e825cd5670dbc33bd6df591d7e3734184cf04071 100644
--- a/src/utils/nsupdate/nsupdate_exec.c
+++ b/src/utils/nsupdate/nsupdate_exec.c
@@ -337,7 +337,7 @@ static int rr_list_to_packet(knot_pkt_t *dst, list_t *list)
 	int ret = KNOT_EOK;
 	ptrnode_t *node = NULL;
 	WALK_LIST(node, *list) {
-		ret = knot_pkt_put(dst, COMPR_HINT_NONE, (knot_rrset_t *)node->d, NULL, 0);
+		ret = knot_pkt_put(dst, COMPR_HINT_NONE, (knot_rrset_t *)node->d, 0);
 		if (ret != KNOT_EOK) {
 			break;
 		}
diff --git a/tests/pkt.c b/tests/pkt.c
index 29e71f76cd46331e25ff505723e10eae6a5d70f1..210322d04f4b98e930b8e80b850ce3deacc4a946 100644
--- a/tests/pkt.c
+++ b/tests/pkt.c
@@ -105,7 +105,7 @@ int main(int argc, char *argv[])
 	/* Write ANSWER section. */
 	rrsets[0] = knot_rrset_new(dnames[0], KNOT_RRTYPE_A, KNOT_CLASS_IN, NULL);
 	knot_rrset_add_rr(rrsets[0], RDVAL(0), RDLEN(0), TTL, NULL);
-	ret = knot_pkt_put(out, COMPR_HINT_QNAME, rrsets[0], NULL, 0);
+	ret = knot_pkt_put(out, COMPR_HINT_QNAME, rrsets[0], 0);
 	ok(ret == KNOT_EOK, "pkt: write ANSWER");
 
 	/* Begin AUTHORITY. */
@@ -117,7 +117,7 @@ int main(int argc, char *argv[])
 	for (unsigned i = 1; i < NAMECOUNT; ++i) {
 		rrsets[i] = knot_rrset_new(dnames[i], KNOT_RRTYPE_NS, KNOT_CLASS_IN, NULL);
 		knot_rrset_add_rr(rrsets[i], RDVAL(i), RDLEN(i), TTL, NULL);
-		ret |= knot_pkt_put(out, COMPR_HINT_NONE, rrsets[i], NULL, 0);
+		ret |= knot_pkt_put(out, COMPR_HINT_NONE, rrsets[i], 0);
 	}
 	ok(ret == KNOT_EOK, "pkt: write AUTHORITY(%u)", NAMECOUNT - 1);
 
diff --git a/tests/process_query.c b/tests/process_query.c
index dbd850f00d667818b24f458ca86e9301e3957d36..437119dc7793c4d79de88329e62fe8e04fe286ba 100644
--- a/tests/process_query.c
+++ b/tests/process_query.c
@@ -196,7 +196,7 @@ int main(int argc, char *argv[])
 	/* Append SOA RR. */
 	knot_rrset_t *soa_rr = knot_node_get_rrset(zone->contents->apex, KNOT_RRTYPE_SOA);
 	knot_pkt_begin(query, KNOT_AUTHORITY);
-	knot_pkt_put(query, COMPR_HINT_NONE, soa_rr, NULL, 0);
+	knot_pkt_put(query, COMPR_HINT_NONE, soa_rr, 0);
 	exec_query(&query_ctx, "IN/ixfr", query->wire, query->size, KNOT_RCODE_NOTAUTH);
 
 	/* \note Tests below are not possible without proper zone and zone data. */