diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/CapCertificateFilter.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/CapCertificateFilter.kt new file mode 100644 index 00000000..2066cc47 --- /dev/null +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/CapCertificateFilter.kt @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2023 Heiko Schaefer +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.wot.dijkstra.filter + +import org.pgpainless.wot.dijkstra.sq.Certification +import org.pgpainless.wot.dijkstra.sq.Fingerprint + +class CapCertificateFilter() : CertificationFilter { + + // A certificate's trust amount will be limited to this amount. + private val caps: HashMap = hashMapOf() + + override fun cost(c: Certification, values: FilterValues, ignoreRegexps: Boolean): Boolean { + caps[c.issuer.fingerprint]?.let { + if (it < values.amount) { + values.amount = it + } + } + + return true + } + + /** + * Add rules for the certificate. + * + * Any certifications issued by the certificate have their trust + * amount limited to `cap`. If a certificate is capped multiple + * times, then the minimum cap is used. + */ + fun cap(cert: Fingerprint, cap: Int) { + val current = caps[cert] + + if ((current == null) || (current > cap)) { + caps[cert] = cap + } + } +} diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/CertificationFilter.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/CertificationFilter.kt new file mode 100644 index 00000000..8fd4a1fb --- /dev/null +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/CertificationFilter.kt @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: 2023 Heiko Schaefer +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.wot.dijkstra.filter + +import org.pgpainless.wot.dijkstra.sq.Certification +import org.pgpainless.wot.dijkstra.sq.Depth +import org.pgpainless.wot.dijkstra.sq.RegexSet + +/** + * Current effective values for `depth`, `amount` and `regexps`. + * + * `regexps` is optional: + * Rewriting the regular expressions may be expensive. By setting regexps to + * `null`, the caller can signal that it doesn't care about the regular expressions. + */ +data class FilterValues(var depth: Depth, var amount: Int, var regexps: RegexSet?) + +/** + * A mechanism to filter certifications. + * + * This function should change the content of `values` in place. + * This enables chaining of multiple filters. + * + * This is particularly useful when evaluating a residual network, + * i.e., a network minus the capacity used by a particular path. + */ +interface CertificationFilter { + + /** + * Filter the certification's parameters. + * + * If the function returns `false`, the certification should be skipped. + */ + fun cost(c: Certification, values: FilterValues, ignoreRegexps: Boolean): Boolean { + return true + } + +} diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/ChainFilter.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/ChainFilter.kt new file mode 100644 index 00000000..f48dcaed --- /dev/null +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/ChainFilter.kt @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2023 Heiko Schaefer +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.wot.dijkstra.filter + +import org.pgpainless.wot.dijkstra.sq.Certification + +/** + * A filter that chains multiple filters together. + * + * The filters are called in the order that they are added. If a + * filter returns `false`, then this filter immediately returns + * false. + */ +class ChainFilter(val filters: MutableList) : CertificationFilter { + + override fun cost(c: Certification, values: FilterValues, ignoreRegexps: Boolean): Boolean { + + // If any inner filter returns `false`, immediately return false + return !this.filters.any { !it.cost(c, values, ignoreRegexps) } + } +} diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/IdempotentCertificationFilter.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/IdempotentCertificationFilter.kt new file mode 100644 index 00000000..e3cb26c3 --- /dev/null +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/IdempotentCertificationFilter.kt @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: 2023 Heiko Schaefer +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.wot.dijkstra.filter + +/** + * A no-op filter. + * + * This filter passes certifications through as is. + */ +class IdempotentCertificationFilter : CertificationFilter \ No newline at end of file diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/SuppressCertificationFilter.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/SuppressCertificationFilter.kt new file mode 100644 index 00000000..e1080b80 --- /dev/null +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/SuppressCertificationFilter.kt @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2023 Heiko Schaefer +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.wot.dijkstra.filter + +import org.pgpainless.wot.dijkstra.sq.Certification +import org.pgpainless.wot.dijkstra.sq.Fingerprint +import org.pgpainless.wot.dijkstra.sq.Path + +class SuppressCertificationFilter() : CertificationFilter { + // A certification's trust amount will be suppressed by this amount. + private val amount: HashMap, Int> = hashMapOf() + + override fun cost(c: Certification, values: FilterValues, ignoreRegexps: Boolean): Boolean { + amount[Pair(c.issuer.fingerprint, c.issuer.fingerprint)]?.let { suppress -> + values.amount = if (values.amount > suppress) { + values.amount - suppress + } else { + 0 + } + } + + return true + } + + /** + * Add suppression rules for all certifications along the specified path. + * + * Each edge is suppressed by `amountToSuppress`. + */ + fun suppressPath(path: Path, amountToSuppress: Int) { + if (amountToSuppress == 0) { + return + } + assert(amountToSuppress <= 120) + + for (c in path.certifications) { + val a = amount[Pair(c.issuer.fingerprint, c.issuer.fingerprint)] + if (a != null) { + val newAmount = a + amountToSuppress + assert(newAmount <= 120) + amount[Pair(c.issuer.fingerprint, c.issuer.fingerprint)] = newAmount + } else { + amount[Pair(c.issuer.fingerprint, c.issuer.fingerprint)] = amountToSuppress + } + } + } +} \ No newline at end of file diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/SuppressIssuerFilter.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/SuppressIssuerFilter.kt new file mode 100644 index 00000000..f699c4a5 --- /dev/null +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/SuppressIssuerFilter.kt @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: 2023 Heiko Schaefer +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.wot.dijkstra.filter + +import org.pgpainless.wot.dijkstra.sq.Certification +import org.pgpainless.wot.dijkstra.sq.Fingerprint + +/** + * A filter that suppresses some capacity of an issuer. + */ +class SuppressIssuerFilter() : CertificationFilter { + // A certification's trust amount will be suppressed by this amount. + private val amount: HashMap = hashMapOf() + + override fun cost(c: Certification, values: FilterValues, ignoreRegexps: Boolean): Boolean { + amount[c.issuer.fingerprint]?.let { suppress -> + values.amount = if (values.amount > suppress) { + values.amount - suppress + } else { + 0 + } + } + + return true + } + + /** + * Add suppression rules for the issuer. + * + * Any certifications that the certificate makes are suppressed + * (decreased) by that amount. + */ + fun suppressIssuer(issuer: Fingerprint, amountToSuppress: Int) { + if (amountToSuppress == 0) { + return + } + assert(amountToSuppress <= 120) + + val a = amount[issuer] + if (a != null) { + val am = a + amountToSuppress + assert(am <= 120) + amount[issuer] = am + } else { + amount[issuer] = amountToSuppress + } + } +} \ No newline at end of file diff --git a/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/TrustedIntroducerFilter.kt b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/TrustedIntroducerFilter.kt new file mode 100644 index 00000000..23ab6e5c --- /dev/null +++ b/wot-dijkstra/src/main/kotlin/org/pgpainless/wot/dijkstra/filter/TrustedIntroducerFilter.kt @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2023 Heiko Schaefer +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.wot.dijkstra.filter + +import org.pgpainless.wot.dijkstra.sq.Certification +import org.pgpainless.wot.dijkstra.sq.Depth + +/** + * A filter that treats every certification as a trust signature with unconstrained depth, + * and no regular expressions. + * + * Note: this filter doesn't change the trust amount. + * + * This filter can be used to view a network as a 'certification network'. + */ +class TrustedIntroducerFilter : CertificationFilter { + override fun cost(c: Certification, values: FilterValues, ignoreRegexps: Boolean): Boolean { + values.depth = Depth.unconstrained() + if (!ignoreRegexps) { + values.regexps = null + } + + return true + } +}