1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-12-25 12:27:58 +01:00

Implementation of Filters

This commit is contained in:
Heiko Schaefer 2023-06-28 15:16:31 +02:00
parent c35a53cffa
commit e42e570911
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D
7 changed files with 247 additions and 0 deletions

View file

@ -0,0 +1,39 @@
// SPDX-FileCopyrightText: 2023 Heiko Schaefer <heiko@schaefer@name>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra.filter
import org.pgpainless.wot.network.EdgeComponent
import org.pgpainless.wot.network.Fingerprint
class CapCertificateFilter() : CertificationFilter {
// A certificate's trust amount will be limited to this amount.
private val caps: HashMap<Fingerprint, Int> = hashMapOf()
override fun cost(ec: EdgeComponent, values: FilterValues, ignoreRegexps: Boolean): Boolean {
caps[ec.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
}
}
}

View file

@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: 2023 Heiko Schaefer <heiko@schaefer@name>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra.filter
import org.pgpainless.wot.network.Depth
import org.pgpainless.wot.network.EdgeComponent
import org.pgpainless.wot.network.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(ec: EdgeComponent, values: FilterValues, ignoreRegexps: Boolean): Boolean {
return true
}
}

View file

@ -0,0 +1,29 @@
// SPDX-FileCopyrightText: 2023 Heiko Schaefer <heiko@schaefer@name>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra.filter
import org.pgpainless.wot.network.EdgeComponent
/**
* 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() : CertificationFilter {
private val filters: MutableList<CertificationFilter> = mutableListOf()
override fun cost(ec: EdgeComponent, values: FilterValues, ignoreRegexps: Boolean): Boolean {
// If any inner filter returns `false`, immediately return false
return !this.filters.any { !it.cost(ec, values, ignoreRegexps) }
}
/**
* Add `filter` to the chain
*/
fun add(filter: CertificationFilter) = filters.add(filter)
}

View file

@ -0,0 +1,12 @@
// SPDX-FileCopyrightText: 2023 Heiko Schaefer <heiko@schaefer@name>
//
// 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

View file

@ -0,0 +1,50 @@
// SPDX-FileCopyrightText: 2023 Heiko Schaefer <heiko@schaefer@name>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra.filter
import org.pgpainless.wot.network.EdgeComponent
import org.pgpainless.wot.network.Fingerprint
import org.pgpainless.wot.query.Path
class SuppressCertificationFilter() : CertificationFilter {
// A certification's trust amount will be suppressed by this amount.
private val amount: HashMap<Pair<Fingerprint, Fingerprint>, Int> = hashMapOf()
override fun cost(ec: EdgeComponent, values: FilterValues, ignoreRegexps: Boolean): Boolean {
amount[Pair(ec.issuer.fingerprint, ec.target.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.target.fingerprint)]
if (a != null) {
val newAmount = a + amountToSuppress
assert(newAmount <= 120)
amount[Pair(c.issuer.fingerprint, c.target.fingerprint)] = newAmount
} else {
amount[Pair(c.issuer.fingerprint, c.target.fingerprint)] = amountToSuppress
}
}
}
}

View file

@ -0,0 +1,50 @@
// SPDX-FileCopyrightText: 2023 Heiko Schaefer <heiko@schaefer@name>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra.filter
import org.pgpainless.wot.network.EdgeComponent
import org.pgpainless.wot.network.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<Fingerprint, Int> = hashMapOf()
override fun cost(ec: EdgeComponent, values: FilterValues, ignoreRegexps: Boolean): Boolean {
amount[ec.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
}
}
}

View file

@ -0,0 +1,27 @@
// SPDX-FileCopyrightText: 2023 Heiko Schaefer <heiko@schaefer@name>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra.filter
import org.pgpainless.wot.network.Depth
import org.pgpainless.wot.network.EdgeComponent
/**
* 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(ec: EdgeComponent, values: FilterValues, ignoreRegexps: Boolean): Boolean {
values.depth = Depth.unconstrained()
if (!ignoreRegexps) {
values.regexps = null
}
return true
}
}