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:
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