mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-24 11:57:59 +01:00
Implementation of Filters
This commit is contained in:
parent
c35a53cffa
commit
e42e570911
7 changed files with 247 additions and 0 deletions
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue