mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-03-17 21:31:57 +01:00
Adds a Bloom-based hint indexer with MurMur hash
This commit is contained in:
parent
94e0f4ed02
commit
aaf86bf53e
@ -75,11 +75,11 @@ import com.vitorpamplona.quartz.experimental.profileGallery.dimension
|
||||
import com.vitorpamplona.quartz.experimental.profileGallery.fromEvent
|
||||
import com.vitorpamplona.quartz.experimental.profileGallery.hash
|
||||
import com.vitorpamplona.quartz.experimental.profileGallery.mimeType
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
|
||||
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.jackson.EventMapper
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate
|
||||
|
@ -40,10 +40,10 @@ import com.vitorpamplona.ammolite.relays.filters.EOSETime
|
||||
import com.vitorpamplona.quartz.experimental.bounties.addedRewardValue
|
||||
import com.vitorpamplona.quartz.experimental.bounties.hasAdditionalReward
|
||||
import com.vitorpamplona.quartz.lightning.LnInvoiceUtil
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
|
||||
|
@ -26,7 +26,7 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.PublicChatChannel
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelMetadataEvent
|
||||
|
@ -66,10 +66,10 @@ import com.vitorpamplona.quartz.experimental.zapPolls.consensusThreshold
|
||||
import com.vitorpamplona.quartz.experimental.zapPolls.maxAmount
|
||||
import com.vitorpamplona.quartz.experimental.zapPolls.minAmount
|
||||
import com.vitorpamplona.quartz.experimental.zapPolls.tags.PollOptionTag
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.eTags
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.geohash.geohash
|
||||
|
@ -165,7 +165,7 @@ import com.vitorpamplona.amethyst.ui.theme.ZeroPadding
|
||||
import com.vitorpamplona.amethyst.ui.theme.innerPostModifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.liveStreamTag
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.isTaggedEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hasHashtags
|
||||
|
@ -0,0 +1,135 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.benchmark
|
||||
|
||||
import androidx.benchmark.junit4.BenchmarkRule
|
||||
import androidx.benchmark.junit4.measureRepeated
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.bloom.BloomFilterMurMur3
|
||||
import com.vitorpamplona.quartz.utils.RandomInstance
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class BloomFilterMurMur3Benchmark {
|
||||
@get:Rule val benchmarkRule = BenchmarkRule()
|
||||
|
||||
val testEncoded = "100:10:AKiEIEQKALgRACEABA==:3"
|
||||
|
||||
val key1 = "ca29c211f1c72d5b6622268ff43d2288ea2b2cb5b9aa196ff9f1704fc914b71b".hexToByteArray()
|
||||
val key2 = "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c".hexToByteArray()
|
||||
val key3 = "560c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c".hexToByteArray()
|
||||
|
||||
val keys =
|
||||
mutableListOf<ByteArray>().apply {
|
||||
for (seed in 0..1000000) {
|
||||
add(RandomInstance.bytes(32))
|
||||
}
|
||||
}
|
||||
|
||||
val keys2 =
|
||||
mutableListOf<ByteArray>().apply {
|
||||
for (seed in 0..1000000) {
|
||||
add(RandomInstance.bytes(32))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addExisting() {
|
||||
val filter = BloomFilterMurMur3.decode(testEncoded)
|
||||
benchmarkRule.measureRepeated {
|
||||
filter.add(key1)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addNew() {
|
||||
val filter = BloomFilterMurMur3.decode(testEncoded)
|
||||
benchmarkRule.measureRepeated {
|
||||
filter.add(key3)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mightContainTrue() {
|
||||
val filter = BloomFilterMurMur3(10_000_000, 5)
|
||||
filter.add(key1)
|
||||
keys.forEach(filter::add)
|
||||
benchmarkRule.measureRepeated {
|
||||
filter.mightContain(key1)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mightContainFalse() {
|
||||
val filter = BloomFilterMurMur3(10_000_000, 5)
|
||||
keys.forEach(filter::add)
|
||||
benchmarkRule.measureRepeated {
|
||||
filter.mightContain(key3)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun decode() {
|
||||
benchmarkRule.measureRepeated {
|
||||
BloomFilterMurMur3.decode(testEncoded)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun encode() {
|
||||
val filter = BloomFilterMurMur3.decode(testEncoded)
|
||||
benchmarkRule.measureRepeated {
|
||||
filter.encode()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun largeFilterBuild() {
|
||||
val bloomFilter = BloomFilterMurMur3(10_000_000, 5)
|
||||
|
||||
benchmarkRule.measureRepeated {
|
||||
keys.forEach(bloomFilter::add)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun largeFilterCheckExisting() {
|
||||
val bloomFilter = BloomFilterMurMur3(10_000_000, 5)
|
||||
keys.forEach(bloomFilter::add)
|
||||
|
||||
benchmarkRule.measureRepeated {
|
||||
keys.forEach(bloomFilter::mightContain)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun largeFilterCheckNew() {
|
||||
val bloomFilter = BloomFilterMurMur3(10_000_000, 5)
|
||||
keys.forEach(bloomFilter::add)
|
||||
|
||||
benchmarkRule.measureRepeated {
|
||||
keys2.forEach(bloomFilter::mightContain)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.benchmark
|
||||
|
||||
import androidx.benchmark.junit4.BenchmarkRule
|
||||
import androidx.benchmark.junit4.measureRepeated
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.HintIndexer
|
||||
import com.vitorpamplona.quartz.utils.RandomInstance
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.nio.charset.Charset
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class HintIndexerBenchmark {
|
||||
@get:Rule val benchmarkRule = BenchmarkRule()
|
||||
|
||||
val keys =
|
||||
mutableListOf<ByteArray>().apply {
|
||||
for (seed in 0..1_000_000) {
|
||||
add(RandomInstance.bytes(32))
|
||||
}
|
||||
}
|
||||
|
||||
val relays =
|
||||
getInstrumentation()
|
||||
.context.assets
|
||||
.open("relayDB.txt")
|
||||
.readBytes()
|
||||
.toString(Charset.forName("utf-8"))
|
||||
.split("\n")
|
||||
|
||||
@Test
|
||||
fun relayUriHashcode() {
|
||||
benchmarkRule.measureRepeated {
|
||||
"wss://relay.bitcoin.social".hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getRelayHints() {
|
||||
val indexer = HintIndexer()
|
||||
|
||||
keys.forEach { key ->
|
||||
(0..5).map {
|
||||
indexer.index(key, relays.random())
|
||||
}
|
||||
}
|
||||
|
||||
val key = keys.random()
|
||||
|
||||
benchmarkRule.measureRepeated {
|
||||
indexer.get(key)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun buildIndexer() {
|
||||
benchmarkRule.measureRepeated {
|
||||
val indexer = HintIndexer()
|
||||
keys.forEach { key ->
|
||||
(0..5).map {
|
||||
indexer.index(key, relays.random())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
2539
quartz/src/androidTest/assets/relayDB.txt
Normal file
2539
quartz/src/androidTest/assets/relayDB.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -49,13 +49,12 @@ class BloomFilter(
|
||||
|
||||
fun add(value: HexKey) = add(value.hexToByteArray())
|
||||
|
||||
fun print(): String {
|
||||
val builder = StringBuilder()
|
||||
for (seed in 0 until bits.size()) {
|
||||
builder.append(if (bits.get(seed)) "1" else "0")
|
||||
fun print() =
|
||||
buildString {
|
||||
for (seed in 0 until bits.size()) {
|
||||
append(if (bits.get(seed)) "1" else "0")
|
||||
}
|
||||
}
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
fun add(value: ByteArray) {
|
||||
lock.write {
|
||||
|
@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.experimental.bounties
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
|
@ -22,11 +22,11 @@ package com.vitorpamplona.quartz.experimental.nip95.header
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.experimental.nip95.data.FileStorageEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.core.any
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.eTag
|
||||
|
@ -18,7 +18,7 @@
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core
|
||||
package com.vitorpamplona.quartz.nip01Core.hints
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.hints
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.bloom.BloomFilterMurMur3
|
||||
|
||||
/**
|
||||
* Instead of having one bloom filter per relay, which could create many
|
||||
* large filters for very few events, this class uses only one mega bloom
|
||||
* filter and uses the hashcode of the relay uri as differentiator in salt.
|
||||
*/
|
||||
class HintIndexer(
|
||||
size: Int = 10_000_000,
|
||||
rounds: Int = 5,
|
||||
) {
|
||||
private val bloomFilter = BloomFilterMurMur3(size, rounds)
|
||||
private val relayDB = hashSetOf<String>()
|
||||
|
||||
fun index(
|
||||
id: ByteArray,
|
||||
relay: String,
|
||||
) {
|
||||
relayDB.add(relay)
|
||||
bloomFilter.add(id, relay.hashCode())
|
||||
}
|
||||
|
||||
fun get(id: ByteArray): List<String> =
|
||||
relayDB.filter {
|
||||
bloomFilter.mightContain(id, it.hashCode())
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.hints
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint
|
||||
|
||||
interface HintProvider {
|
||||
fun eventHints(): EventIdHint
|
||||
|
||||
fun addressIdHints(): AddressHint
|
||||
|
||||
fun pubKeyHints(): PubKeyHint
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.hints.bloom
|
||||
|
||||
import java.util.BitSet
|
||||
|
||||
fun BitSet.printBits() =
|
||||
buildString {
|
||||
for (seed in 0 until size()) {
|
||||
append(if (this@printBits.get(seed)) "1" else "0")
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.hints.bloom
|
||||
|
||||
import com.vitorpamplona.quartz.utils.RandomInstance
|
||||
import java.util.Base64
|
||||
import java.util.BitSet
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import kotlin.concurrent.read
|
||||
import kotlin.concurrent.write
|
||||
|
||||
class BloomFilterMurMur3(
|
||||
private val size: Int,
|
||||
private val rounds: Int,
|
||||
private val bits: BitSet = BitSet(size),
|
||||
private val commonSalt: Int = RandomInstance.int(),
|
||||
) {
|
||||
private val hasher = MurmurHash3()
|
||||
private val lock = ReentrantReadWriteLock()
|
||||
|
||||
fun add(
|
||||
value: ByteArray,
|
||||
salt: Int = commonSalt,
|
||||
) {
|
||||
lock.write {
|
||||
repeat(rounds) {
|
||||
bits.set(hash(value, salt + it))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun mightContain(
|
||||
value: ByteArray,
|
||||
salt: Int = commonSalt,
|
||||
): Boolean {
|
||||
lock.read {
|
||||
repeat(rounds) {
|
||||
if (!bits.get(hash(value, salt + it))) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private fun hash(
|
||||
value: ByteArray,
|
||||
seed: Int,
|
||||
) = hasher.hash(value, seed).mod(size)
|
||||
|
||||
fun encode() = encode(this)
|
||||
|
||||
fun printBits() = bits.printBits()
|
||||
|
||||
companion object {
|
||||
fun encode(f: BloomFilterMurMur3): String {
|
||||
val bitSetB64 = Base64.getEncoder().encodeToString(f.bits.toByteArray())
|
||||
return "${f.size}:${f.rounds}:$bitSetB64:${f.commonSalt}"
|
||||
}
|
||||
|
||||
fun decode(encodedStr: String): BloomFilterMurMur3 {
|
||||
val (sizeStr, roundsStr, filterB64, salt) = encodedStr.split(":")
|
||||
val bitSet = BitSet.valueOf(Base64.getDecoder().decode(filterB64))
|
||||
return BloomFilterMurMur3(sizeStr.toInt(), roundsStr.toInt(), bitSet, salt.toInt())
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.hints.bloom
|
||||
|
||||
class MurmurHash3 {
|
||||
fun hash(
|
||||
data: ByteArray,
|
||||
seed: Int,
|
||||
) = hash(data, 0, data.size, seed)
|
||||
|
||||
/**
|
||||
* Generates 32 bit hash .
|
||||
* @param data the byte array to hash
|
||||
* @param offset the start offset of the data in the array (always 0)
|
||||
* @param length the length of the data in the array
|
||||
* @param seed the seed for the hash (int)
|
||||
* @return 32 bit hash of the given array
|
||||
*/
|
||||
fun hash(
|
||||
data: ByteArray,
|
||||
offset: Int,
|
||||
length: Int,
|
||||
seed: Int,
|
||||
): Int {
|
||||
val c1 = -0x3361d2af // 0xcc9e2d51
|
||||
val c2 = 0x1b873593
|
||||
var h1 = seed
|
||||
val roundedEnd = offset + (length and 0xFFFFFFFC.toInt()) // Round down to 4-byte blocks
|
||||
|
||||
var i = offset
|
||||
while (i < roundedEnd) {
|
||||
var k1 =
|
||||
(data[i].toInt() and 0xFF) or
|
||||
((data[i + 1].toInt() and 0xFF) shl 8) or
|
||||
((data[i + 2].toInt() and 0xFF) shl 16) or
|
||||
((data[i + 3].toInt() and 0xFF) shl 24)
|
||||
|
||||
i += 4
|
||||
|
||||
k1 *= c1
|
||||
k1 = Integer.rotateLeft(k1, 15)
|
||||
k1 *= c2
|
||||
|
||||
h1 = h1 xor k1
|
||||
h1 = Integer.rotateLeft(h1, 13)
|
||||
h1 = h1 * 5 + -0x19ab949c // 0xe6546b64
|
||||
}
|
||||
|
||||
// processing tail (remaining bytes)
|
||||
var k1 = 0
|
||||
when (length and 3) {
|
||||
3 -> {
|
||||
k1 = k1 or ((data[i + 2].toInt() and 0xFF) shl 16)
|
||||
k1 = k1 or ((data[i + 1].toInt() and 0xFF) shl 8)
|
||||
k1 = k1 or (data[i].toInt() and 0xFF)
|
||||
|
||||
k1 *= c1
|
||||
k1 = Integer.rotateLeft(k1, 15)
|
||||
k1 *= c2
|
||||
|
||||
h1 = h1 xor k1
|
||||
}
|
||||
|
||||
2 -> {
|
||||
k1 = k1 or (data[i + 1].toInt() and 0xFF shl 8)
|
||||
k1 = k1 or (data[i].toInt() and 0xFF)
|
||||
|
||||
k1 *= c1
|
||||
k1 = Integer.rotateLeft(k1, 15)
|
||||
k1 *= c2
|
||||
|
||||
h1 = h1 xor k1
|
||||
}
|
||||
|
||||
1 -> {
|
||||
k1 = k1 or (data[i].toInt() and 0xFF)
|
||||
|
||||
k1 *= c1
|
||||
k1 = Integer.rotateLeft(k1, 15)
|
||||
k1 *= c2
|
||||
|
||||
h1 = h1 xor k1
|
||||
}
|
||||
}
|
||||
|
||||
// final mix
|
||||
h1 = h1 xor length
|
||||
h1 = fmix32(h1)
|
||||
|
||||
return h1
|
||||
}
|
||||
|
||||
private fun fmix32(h: Int): Int {
|
||||
var f = h
|
||||
f = f xor (f ushr 16)
|
||||
f *= -0x7a143595 // 0x85ebca6b
|
||||
f = f xor (f ushr 13)
|
||||
f *= -0x3d4d51cb // 0xc2b2ae35
|
||||
f = f xor (f ushr 16)
|
||||
|
||||
return f
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.hints.types
|
||||
|
||||
class AddressHint(
|
||||
val addressId: String,
|
||||
var relay: String? = null,
|
||||
) : Hint {
|
||||
override fun id() = addressId.toByteArray(Charsets.UTF_8)
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.hints.types
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
|
||||
|
||||
class EventIdHint(
|
||||
val eventId: HexKey,
|
||||
var relay: String? = null,
|
||||
) : Hint {
|
||||
override fun id() = eventId.hexToByteArray()
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.hints.types
|
||||
|
||||
interface Hint {
|
||||
fun id(): ByteArray
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.hints.types
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
|
||||
|
||||
class PubKeyHint(
|
||||
val pubkey: HexKey,
|
||||
var relay: String? = null,
|
||||
) : Hint {
|
||||
override fun id() = pubkey.hexToByteArray()
|
||||
}
|
@ -21,11 +21,11 @@
|
||||
package com.vitorpamplona.quartz.nip03Timestamp
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.eTag
|
||||
|
@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip04Dm.messages
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.EventReference
|
||||
import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag
|
||||
|
||||
|
@ -21,9 +21,9 @@
|
||||
package com.vitorpamplona.quartz.nip10Notes
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip10Notes.tags.markedETags
|
||||
import com.vitorpamplona.quartz.nip10Notes.tags.prepareETagsAsReplyTo
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip10Notes.tags
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent
|
||||
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
||||
|
||||
|
@ -20,9 +20,9 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip17Dm
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.nip17Dm.files.ChatMessageEncryptedFileHeaderEvent
|
||||
|
@ -21,9 +21,9 @@
|
||||
package com.vitorpamplona.quartz.nip17Dm.files
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
|
@ -20,9 +20,9 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip17Dm.files
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.pTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.pTags
|
||||
|
@ -21,9 +21,9 @@
|
||||
package com.vitorpamplona.quartz.nip17Dm.messages
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
|
@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip17Dm.messages
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.pTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.pTags
|
||||
|
@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip21UriScheme
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip19Bech32.toNIP19
|
||||
|
||||
fun Event.toNostrUri(): String = "nostr:${toNIP19()}"
|
||||
|
@ -21,11 +21,11 @@
|
||||
package com.vitorpamplona.quartz.nip22Comments
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent
|
||||
import com.vitorpamplona.quartz.nip21UriScheme.toNostrUri
|
||||
|
@ -21,10 +21,10 @@
|
||||
package com.vitorpamplona.quartz.nip25Reactions
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.aTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
|
@ -21,9 +21,9 @@
|
||||
package com.vitorpamplona.quartz.nip28PublicChat.admin
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.eTags
|
||||
|
@ -21,9 +21,9 @@
|
||||
package com.vitorpamplona.quartz.nip28PublicChat.admin
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.base.BasePublicChatEvent
|
||||
|
@ -21,9 +21,9 @@
|
||||
package com.vitorpamplona.quartz.nip28PublicChat.admin
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.pTags
|
||||
|
@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip28PublicChat.base
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.pTag
|
||||
|
@ -21,9 +21,9 @@
|
||||
package com.vitorpamplona.quartz.nip28PublicChat.message
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent
|
||||
|
@ -21,10 +21,10 @@
|
||||
package com.vitorpamplona.quartz.nip30CustomEmoji.selection
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.BaseReplaceableEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventUpdate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
|
||||
|
@ -21,9 +21,9 @@
|
||||
package com.vitorpamplona.quartz.nip34Git.issue
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags
|
||||
|
@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip34Git.issue
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.pTags
|
||||
|
@ -21,9 +21,9 @@
|
||||
package com.vitorpamplona.quartz.nip34Git.reply
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag
|
||||
import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent
|
||||
|
@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip34Git.reply
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.pTags
|
||||
|
@ -21,9 +21,9 @@
|
||||
package com.vitorpamplona.quartz.nip35Torrents
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
|
@ -21,9 +21,9 @@
|
||||
package com.vitorpamplona.quartz.nip53LiveActivities.chat
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag
|
||||
import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent
|
||||
|
@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip53LiveActivities.chat
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.pTag
|
||||
|
@ -22,10 +22,10 @@ package com.vitorpamplona.quartz.nip72ModCommunities.approval
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.taggedATags
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.taggedAddresses
|
||||
|
@ -20,10 +20,10 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip72ModCommunities.approval
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip72ModCommunities.definition.CommunityDefinitionEvent
|
||||
|
||||
fun TagArrayBuilder<CommunityPostApprovalEvent>.community(event: EventHintBundle<CommunityDefinitionEvent>) = add(event.toATag().toATagArray())
|
||||
|
@ -21,12 +21,12 @@
|
||||
package com.vitorpamplona.quartz.nip75ZapGoals
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.BaseAddressableEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.references.reference
|
||||
|
@ -25,7 +25,7 @@ import java.security.SecureRandom
|
||||
object RandomInstance {
|
||||
private val randomizer = SecureRandom()
|
||||
|
||||
fun int(bound: Int) = randomizer.nextInt(bound)
|
||||
fun int(bound: Int = Int.MAX_VALUE) = randomizer.nextInt(bound)
|
||||
|
||||
fun bytes(size: Int) = ByteArray(size).also { randomizer.nextBytes(it) }
|
||||
}
|
||||
|
@ -0,0 +1,114 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.hints
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.bloom.BloomFilterMurMur3
|
||||
import com.vitorpamplona.quartz.utils.RandomInstance
|
||||
import junit.framework.TestCase.assertEquals
|
||||
import junit.framework.TestCase.assertFalse
|
||||
import junit.framework.TestCase.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class BloomFilterMurMur3Test {
|
||||
val testEncoded = "100:10:AKiEIEQKALgRACEABA==:3"
|
||||
val testInBinary = "00000000000101010010000100000100001000100101000000000000000111011000100000000000100001000000000000100000000000000000000000000000"
|
||||
|
||||
val key1 = "ca29c211f1c72d5b6622268ff43d2288ea2b2cb5b9aa196ff9f1704fc914b71b".hexToByteArray()
|
||||
val key2 = "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c".hexToByteArray()
|
||||
val key3 = "560c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c".hexToByteArray()
|
||||
|
||||
val keys =
|
||||
mutableListOf<ByteArray>().apply {
|
||||
for (seed in 0..1_000_000) {
|
||||
add(RandomInstance.bytes(32))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCreate() {
|
||||
val bloomFilter = BloomFilterMurMur3(100, 10, commonSalt = 3)
|
||||
bloomFilter.add(key1)
|
||||
bloomFilter.add(key2)
|
||||
|
||||
assertEquals(testEncoded, bloomFilter.encode())
|
||||
assertEquals(testInBinary, bloomFilter.printBits())
|
||||
|
||||
assertTrue(bloomFilter.mightContain(key1))
|
||||
assertTrue(bloomFilter.mightContain(key2))
|
||||
|
||||
assertFalse(bloomFilter.mightContain(key3))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDecoding() {
|
||||
val bloomFilter = BloomFilterMurMur3.decode(testEncoded)
|
||||
|
||||
assertEquals(testEncoded, bloomFilter.encode())
|
||||
assertEquals(testInBinary, bloomFilter.printBits())
|
||||
|
||||
assertTrue(bloomFilter.mightContain(key1))
|
||||
assertTrue(bloomFilter.mightContain(key2))
|
||||
|
||||
assertFalse(bloomFilter.mightContain(key3))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun runProb() {
|
||||
val bloomFilter = BloomFilterMurMur3.decode(testEncoded)
|
||||
|
||||
var failureCounter = 0
|
||||
repeat(1_000_000) {
|
||||
if (bloomFilter.mightContain(RandomInstance.bytes(32))) {
|
||||
failureCounter++
|
||||
}
|
||||
}
|
||||
assertEquals(0, failureCounter)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun runProb2() {
|
||||
val bloomFilter = BloomFilterMurMur3(10_000_000, 4)
|
||||
keys.forEach(bloomFilter::add)
|
||||
|
||||
var failureCounter = 0
|
||||
repeat(1_000_000) {
|
||||
if (bloomFilter.mightContain(RandomInstance.bytes(32))) {
|
||||
failureCounter++
|
||||
}
|
||||
}
|
||||
assertTrue("Failures $failureCounter ${failureCounter / 1_000_000.0}", failureCounter / 1_000_000.0f < 0.015)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun runProb3() {
|
||||
val bloomFilter = BloomFilterMurMur3(10_000_000, 4)
|
||||
keys.forEach(bloomFilter::add)
|
||||
|
||||
var failureCounter = 0
|
||||
repeat(1_000_000) {
|
||||
if (bloomFilter.mightContain(RandomInstance.bytes(32))) {
|
||||
failureCounter++
|
||||
}
|
||||
}
|
||||
assertTrue("Failures $failureCounter ${failureCounter / 1_000_000.0}", failureCounter / 1_000_000.0f < 0.015)
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.hints
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
|
||||
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint
|
||||
import com.vitorpamplona.quartz.utils.RandomInstance
|
||||
import junit.framework.TestCase.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class HintIndexerTest {
|
||||
val key1 = "ca29c211f1c72d5b6622268ff43d2288ea2b2cb5b9aa196ff9f1704fc914b71b".hexToByteArray()
|
||||
val key2 = "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c".hexToByteArray()
|
||||
val key3 = "560c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c".hexToByteArray()
|
||||
|
||||
val keys =
|
||||
mutableListOf<HexKey>().apply {
|
||||
for (seed in 0..1_000_000) {
|
||||
add(RandomInstance.bytes(32).toHexKey())
|
||||
}
|
||||
}
|
||||
|
||||
val relays =
|
||||
this.javaClass
|
||||
.getResourceAsStream("relayDB.txt")
|
||||
?.readAllBytes()
|
||||
.toString()
|
||||
.split("\n")
|
||||
|
||||
val keyHints =
|
||||
keys
|
||||
.map { key ->
|
||||
(0..5).map { PubKeyHint(key, relays.random()) }
|
||||
}.flatten()
|
||||
|
||||
val key1Relays = (0..5).map { relays.random() }
|
||||
val key2Relays = (0..4).map { relays.random() }
|
||||
val key3Relays = (0..3).map { relays.random() }
|
||||
|
||||
@Test
|
||||
fun runExistingKeys() {
|
||||
val indexer = HintIndexer()
|
||||
keyHints.forEach {
|
||||
indexer.index(it.id(), it.relay!!)
|
||||
}
|
||||
|
||||
var failureCounter = 0
|
||||
repeat(1000) {
|
||||
val key = keys.random()
|
||||
if (indexer.get(key.hexToByteArray()).isEmpty()) {
|
||||
failureCounter++
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue("Failures $failureCounter ${failureCounter / 1_000.0}", failureCounter / 1_000.0f < 0.015)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun runProb() {
|
||||
val indexer = HintIndexer()
|
||||
keyHints.forEach {
|
||||
indexer.index(it.id(), it.relay!!)
|
||||
}
|
||||
|
||||
var failureCounter = 0
|
||||
repeat(1_000) {
|
||||
if (indexer.get(RandomInstance.bytes(32)).isNotEmpty()) {
|
||||
failureCounter++
|
||||
}
|
||||
}
|
||||
assertTrue("Failures $failureCounter ${failureCounter / 1_000.0}", failureCounter / 1_000.0f < 0.015)
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user