From 442f75fc41f6ca020da73a633e5c5b93fa723eb7 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Wed, 27 Aug 2025 17:32:39 -0400 Subject: [PATCH] - Migrates Quartz to a KMP project - Converts OpenTimestamps from java to Kotlin - Moves OTS OkHttp setup to Quartz --- .gitignore | 1 + README.md | 2 +- .../vitorpamplona/amethyst/OkHttpOtsTest.kt | 6 +- .../com/vitorpamplona/amethyst/Amethyst.kt | 2 +- .../vitorpamplona/amethyst/model/Account.kt | 6 +- .../amethyst/model/nip03Timestamp/OtsState.kt | 2 +- ammolite/build.gradle | 4 +- build.gradle | 15 +- commons/build.gradle | 1 - gradle/libs.versions.toml | 18 +- quartz/build.gradle | 88 --- quartz/build.gradle.kts | 157 +++++ quartz/notebooks/Kind1Test.ipynb | 147 ---- .../AndroidManifest.xml | 0 .../assets/bip39.vectors.json | 0 .../assets/github_amethyst.html | 0 .../assets/nip44.vectors.json | 0 .../assets/nostr_vitor_short.json | 0 .../assets/nostr_vitor_startup_data.json | Bin .../assets/ovxxk2vz.jpg | Bin .../assets/relayDB.txt | 0 .../assets/trouble_video | Bin .../quartz/LargeDBSignatureCheck.kt | 0 .../vitorpamplona/quartz/bloom/BloomFilter.kt | 0 .../quartz/lightning/LnInvoiceUtilTest.kt | 0 .../quartz/nip01Core/EventSigCheck.kt | 0 .../quartz/nip01Core/Nip01Test.kt | 0 .../nip01Core/crypto/Nip01CryptoTest.kt | 0 .../nip01Core/store/sqlite/AddressableTest.kt | 0 .../nip01Core/store/sqlite/AssertUtils.kt | 0 .../nip01Core/store/sqlite/BasicTest.kt | 0 .../nip01Core/store/sqlite/DeletionTest.kt | 0 .../nip01Core/store/sqlite/ExpirationTest.kt | 0 .../nip01Core/store/sqlite/LargeDBTests.kt | 0 .../nip01Core/store/sqlite/ReplaceableTest.kt | 0 .../store/sqlite/RightToVanishTest.kt | 0 .../nip01Core/store/sqlite/SearchTest.kt | 0 .../quartz/nip03Timestamp/ots/OtsTest.kt | 11 - .../quartz/nip04Dm/EncryptionTest.kt | 0 .../vitorpamplona/quartz/nip04Dm/Nip04Test.kt | 0 .../Bip32SeedDerivationTest.kt | 0 .../nip06KeyDerivation/Bip39KeyPathTest.kt | 0 .../nip06KeyDerivation/Bip39MnemonicsTest.kt | 0 .../quartz/nip06KeyDerivation/Nip06Test.kt | 0 .../quartz/nip10Notes/CitationTests.kt | 0 .../quartz/nip10Notes/ThreadingTests.kt | 0 .../quartz/nip13Pow/PoWMinerTest.kt | 0 .../quartz/nip13Pow/PoWRankEvaluatorTest.kt | 0 .../quartz/nip17Dm/AESGCMTest.kt | 0 .../quartz/nip17Dm/ChatroomKeyTest.kt | 0 .../quartz/nip19Bech32/NIP19EmbedTests.kt | 0 .../nip22Comments/GeolocatedComments.kt | 0 .../quartz/nip44Encryption/Nip44v1Test.kt | 0 .../quartz/nip44Encryption/Nip44v2Test.kt | 0 .../nip44Encryption/TestPackageClasses.kt | 0 .../quartz/nip46RemoteSigner/Nip46Test.kt | 0 .../quartz/nip49PrivKeyEnc/NIP49Test.kt | 0 .../nip55AndroidSigner/SignStringTest.kt | 0 .../quartz/nip57Zaps/PrivateZapTests.kt | 0 .../nip59GiftWraps/GiftWrapEventTest.kt | 0 .../quartz/utils/HexEncodingTest.kt | 0 .../quartz/lightning/Lud06Test.kt | 0 .../nip01Core/hints/BloomFilterMurMur3Test.kt | 0 .../quartz/nip01Core/hints/HintIndexerTest.kt | 0 .../quartz/nip01Core/hints/MurMur3Test.kt | 0 .../quartz/nip01Core/hints/relayDB.txt | 0 .../jackson/EventDeserializerTest.kt | 0 .../InliningTagArrayPrettyPrinterTest.kt | 0 .../nip01Core/metadata/UpdateMetadataTest.kt | 0 .../nip01Core/relay/RelayUrlFormatterTest.kt | 0 .../store/sqlite/EventDbQueryAssemblerTest.kt | 0 .../quartz/nip05DnsIdentifiers/Nip05Test.kt | 0 .../quartz/nip19Bech32/NIP19ParserTest.kt | 0 .../quartz/nip19Bech32/TlvIntegerTest.kt | 0 .../quartz/nip30CustomEmoji/Nip30Test.kt | 0 .../nip46RemoteSigner/BunkerRequestTest.kt | 0 .../quartz/nip51Lists/TagArrayExt.kt | 0 .../RelayListRecommendationProcessorTest.kt | 0 .../quartz/nip96FileStorage/Nip96Test.kt | 0 .../quartz/utils/HexEncodingTest.kt | 0 .../vitorpamplona/quartz/utils/RuntimeExt.kt | 0 .../vitorpamplona/quartz/utils/SignerUtils.kt | 0 .../quartz/utils/StringUtilsTest.kt | 0 quartz/src/androidMain/AndroidManifest.xml | 4 + .../com/vitorpamplona/quartz/EventFactory.kt | 0 .../vitorpamplona/quartz/Platform.android.kt | 23 + .../audio/header/AudioHeaderEvent.kt | 0 .../audio/header/TagArrayBuilderExt.kt | 0 .../audio/header/tags/DownloadUrlTag.kt | 0 .../audio/header/tags/StreamUrlTag.kt | 0 .../audio/header/tags/WaveformTag.kt | 0 .../audio/track/AudioTrackEvent.kt | 0 .../audio/track/TagArrayBuilderExt.kt | 0 .../experimental/audio/track/tags/CoverTag.kt | 0 .../experimental/audio/track/tags/MediaTag.kt | 0 .../audio/track/tags/ParticipantTag.kt | 0 .../experimental/audio/track/tags/PriceTag.kt | 0 .../experimental/audio/track/tags/TypeTag.kt | 0 .../bounties/BountyAddValueEvent.kt | 0 .../quartz/experimental/bounties/EventExt.kt | 0 .../quartz/experimental/bounties/RewardTag.kt | 0 .../experimental/bounties/TagArrayExt.kt | 0 .../decoupling/DecoupledCipher.kt | 0 .../decoupling/EncryptionKeyCache.kt | 0 .../decoupling/EncryptionKeyDerivation.kt | 0 .../setup/EncryptionKeyListEvent.kt | 0 .../decoupling/setup/TagArrayBuilderExt.kt | 0 .../decoupling/setup/tags/KeyTag.kt | 0 .../edits/TextNoteModificationEvent.kt | 0 .../ephemChat/chat/EphemeralChatEvent.kt | 0 .../experimental/ephemChat/chat/RoomId.kt | 0 .../ephemChat/chat/TagArrayBuilderExt.kt | 0 .../ephemChat/chat/tags/RelayTag.kt | 0 .../ephemChat/chat/tags/RoomTag.kt | 0 .../ephemChat/db/EphemeralRoom.kt | 0 .../ephemChat/db/EphemeralRoomCache.kt | 0 .../ephemChat/list/EphemeralChatListEvent.kt | 0 .../ephemChat/list/TagArrayBuilderExt.kt | 0 .../ephemChat/list/TagArrayExt.kt | 0 .../ephemChat/list/tags/RoomIdTag.kt | 0 .../forks/BaseThreadedEventExt.kt | 0 .../experimental/forks/MarkedETagExt.kt | 0 .../inlineMetadata/Nip54InlineMetadata.kt | 0 .../InteractiveStoryBaseEvent.kt | 0 .../InteractiveStoryPrologueEvent.kt | 0 .../InteractiveStoryReadingStateEvent.kt | 0 .../InteractiveStorySceneEvent.kt | 0 .../interactiveStories/TagArrayBuilderExt.kt | 0 .../interactiveStories/tags/ReadStatusTag.kt | 0 .../interactiveStories/tags/RootSceneTag.kt | 0 .../interactiveStories/tags/StoryOptionTag.kt | 0 .../experimental/limits/LimitProcessor.kt | 0 .../quartz/experimental/limits/Limits.kt | 0 .../experimental/medical/FhirResourceEvent.kt | 0 .../nip95/data/FileStorageEvent.kt | 0 .../nip95/data/TagArrayBuilderExt.kt | 0 .../nip95/header/FileStorageHeaderEvent.kt | 0 .../nip95/header/TagArrayBuilderExt.kt | 0 .../quartz/experimental/nns/NNSEvent.kt | 0 .../experimental/nns/TagArrayBuilderExt.kt | 0 .../quartz/experimental/nns/tags/IPv4Tag.kt | 0 .../quartz/experimental/nns/tags/IPv6Tag.kt | 0 .../experimental/nns/tags/VersionTag.kt | 0 .../profileGallery/GalleryListEvent.kt | 0 .../ProfileGalleryEntryEvent.kt | 0 .../profileGallery/TagArrayBuilderExt.kt | 0 .../publicMessages/PublicMessageEvent.kt | 0 .../publicMessages/TagArrayBuilderExt.kt | 0 .../publicMessages/tags/ReceiverTag.kt | 0 .../RelationshipStatusEvent.kt | 0 .../relationshipStatus/TagArrayBuilderExt.kt | 0 .../relationshipStatus/tags/PetNameTag.kt | 0 .../relationshipStatus/tags/RankTag.kt | 0 .../relationshipStatus/tags/SummaryTag.kt | 0 .../experimental/zapPolls/PollNoteEvent.kt | 0 .../zapPolls/TagArrayBuilderExt.kt | 0 .../experimental/zapPolls/tags/ClosedAtTag.kt | 0 .../zapPolls/tags/ConsensusThresholdTag.kt | 0 .../experimental/zapPolls/tags/MaximumTag.kt | 0 .../experimental/zapPolls/tags/MinimumTag.kt | 0 .../zapPolls/tags/PollOptionTag.kt | 0 .../quartz/lightning/LnInvoiceUtil.kt | 0 .../quartz/lightning/LnWithdrawalUtil.kt | 0 .../vitorpamplona/quartz/lightning/Lud06.kt | 0 .../quartz/nip01Core/EventExt.kt | 0 .../quartz/nip01Core/core/AddressableEvent.kt | 0 .../nip01Core/core/BaseAddressableEvent.kt | 0 .../nip01Core/core/BaseReplaceableEvent.kt | 0 .../quartz/nip01Core/core/Event.kt | 0 .../quartz/nip01Core/core/HexKey.kt | 0 .../quartz/nip01Core/core/IEvent.kt | 0 .../quartz/nip01Core/core/Kind.kt | 0 .../quartz/nip01Core/core/Tag.kt | 0 .../quartz/nip01Core/core/TagArray.kt | 0 .../quartz/nip01Core/core/TagArrayBuilder.kt | 0 .../nip01Core/crypto/DeterministicSigner.kt | 0 .../quartz/nip01Core/crypto/EventAssembler.kt | 0 .../quartz/nip01Core/crypto/EventHasher.kt | 0 .../quartz/nip01Core/crypto/KeyPair.kt | 0 .../quartz/nip01Core/crypto/Nip01.kt | 0 .../quartz/nip01Core/hints/EventHintBundle.kt | 0 .../quartz/nip01Core/hints/HintIndexer.kt | 0 .../quartz/nip01Core/hints/HintProviders.kt | 0 .../quartz/nip01Core/hints/bloom/BitSetExt.kt | 0 .../hints/bloom/BloomFilterMurMur3.kt | 0 .../nip01Core/hints/bloom/MurmurHash3.kt | 0 .../nip01Core/hints/types/AddressHint.kt | 0 .../nip01Core/hints/types/EventIdHint.kt | 0 .../quartz/nip01Core/hints/types/Hint.kt | 0 .../nip01Core/hints/types/PubKeyHint.kt | 0 .../nip01Core/jackson/EventDeserializer.kt | 0 .../jackson/EventManualDeserializer.kt | 0 .../jackson/EventManualSerializer.kt | 0 .../nip01Core/jackson/EventSerializer.kt | 0 .../jackson/InliningTagArrayPrettyPrinter.kt | 0 .../quartz/nip01Core/jackson/JacksonExt.kt | 0 .../quartz/nip01Core/jackson/JsonMapper.kt | 0 .../nip01Core/jackson/TagArrayDeserializer.kt | 0 .../jackson/TagArrayManualDeserializer.kt | 0 .../nip01Core/jackson/TagArraySerializer.kt | 0 .../nip01Core/metadata/MetadataEvent.kt | 0 .../nip01Core/metadata/TagArrayBuilderExt.kt | 0 .../quartz/nip01Core/metadata/UserMetadata.kt | 0 .../nip01Core/metadata/tags/AboutTag.kt | 0 .../nip01Core/metadata/tags/BannerTag.kt | 0 .../nip01Core/metadata/tags/DisplayNameTag.kt | 0 .../nip01Core/metadata/tags/Lud06Tag.kt | 0 .../nip01Core/metadata/tags/Lud16Tag.kt | 0 .../quartz/nip01Core/metadata/tags/NameTag.kt | 0 .../nip01Core/metadata/tags/Nip05Tag.kt | 0 .../nip01Core/metadata/tags/PictureTag.kt | 0 .../nip01Core/metadata/tags/PronounsTag.kt | 0 .../nip01Core/metadata/tags/WebsiteTag.kt | 0 .../nip01Core/relay/client/NostrClient.kt | 0 .../relay/client/NostrClientSubscription.kt | 0 .../client/accessories/EventCollector.kt | 0 .../accessories/NostrClientSendAndWaitExt.kt | 0 .../NostrClientSingleDownloadExt.kt | 0 .../client/accessories/RelayAuthenticator.kt | 0 .../RelayInsertConfirmationCollector.kt | 0 .../relay/client/accessories/RelayLogger.kt | 0 .../relay/client/accessories/RelayNotifier.kt | 0 .../client/listeners/IRelayClientListener.kt | 0 .../listeners/RedirectRelayClientListener.kt | 0 .../relay/client/pool/PoolEventOutbox.kt | 0 .../client/pool/PoolEventOutboxRepository.kt | 0 .../client/pool/PoolSubscriptionRepository.kt | 0 .../relay/client/pool/RelayBasedFilter.kt | 0 .../nip01Core/relay/client/pool/RelayPool.kt | 0 .../relay/client/single/IRelayClient.kt | 0 .../relay/client/single/Subscription.kt | 0 .../client/single/basic/BasicRelayClient.kt | 0 .../relay/client/single/simple/OutboxCache.kt | 0 .../client/single/simple/SimpleRelayClient.kt | 0 .../nip01Core/relay/client/stats/RelayStat.kt | 0 .../relay/client/stats/RelayStats.kt | 0 .../client/subscriptions/Subscription.kt | 0 .../subscriptions/SubscriptionController.kt | 0 .../client/subscriptions/SubscriptionStats.kt | 0 .../relay/commands/toClient/AuthMessage.kt | 0 .../relay/commands/toClient/ClosedMessage.kt | 0 .../relay/commands/toClient/EoseMessage.kt | 0 .../relay/commands/toClient/EventMessage.kt | 0 .../relay/commands/toClient/Message.kt | 0 .../relay/commands/toClient/NoticeMessage.kt | 0 .../relay/commands/toClient/NotifyMessage.kt | 0 .../relay/commands/toClient/OkMessage.kt | 0 .../relay/commands/toClient/ToClientParser.kt | 0 .../relay/commands/toRelay/AuthCmd.kt | 0 .../relay/commands/toRelay/CloseCmd.kt | 0 .../relay/commands/toRelay/Command.kt | 0 .../relay/commands/toRelay/CountCmd.kt | 0 .../relay/commands/toRelay/EventCmd.kt | 0 .../relay/commands/toRelay/ReqCmd.kt | 0 .../relay/commands/toRelay/ToRelayParser.kt | 0 .../quartz/nip01Core/relay/filters/Filter.kt | 0 .../relay/filters/FilterDeserializer.kt | 0 .../nip01Core/relay/filters/FilterMatcher.kt | 0 .../relay/filters/FilterSerializer.kt | 0 .../relay/normalizer/NormalizedRelayUrl.kt | 0 .../relay/normalizer/RelayUrlNormalizer.kt | 0 .../nip01Core/relay/sockets/WebSocket.kt | 0 .../relay/sockets/WebSocketListener.kt | 0 .../relay/sockets/WebsocketBuilder.kt | 0 .../relay/sockets/WebsocketBuilderFactory.kt | 0 .../sockets/okhttp/BasicOkHttpWebSocket.kt | 0 .../quartz/nip01Core/signers/EventTemplate.kt | 0 .../signers/EventTemplateDeserializer.kt | 0 .../EventTemplateManualDeserializer.kt | 0 .../quartz/nip01Core/signers/NostrSigner.kt | 0 .../nip01Core/signers/NostrSignerInternal.kt | 0 .../nip01Core/signers/NostrSignerSync.kt | 0 .../nip01Core/signers/SignerExceptions.kt | 0 .../nip01Core/signers/caches/CacheResults.kt | 0 .../nip01Core/signers/caches/DecryptCache.kt | 0 .../quartz/nip01Core/store/README.md | 0 .../store/sqlite/AddressableModule.kt | 0 .../store/sqlite/DeletionRequestModule.kt | 0 .../nip01Core/store/sqlite/EphemeralModule.kt | 0 .../store/sqlite/EventIndexesModule.kt | 0 .../nip01Core/store/sqlite/EventStore.kt | 0 .../store/sqlite/ExpirationModule.kt | 0 .../store/sqlite/FullTextSearchModule.kt | 0 .../store/sqlite/ReplaceableModule.kt | 0 .../store/sqlite/RightToVanishModule.kt | 0 .../store/sqlite/SQLiteEventStore.kt | 0 .../nip01Core/store/sqlite/StatementCache.kt | 0 .../nip01Core/store/sqlite/sql/Condition.kt | 0 .../store/sqlite/sql/SqlSelectionBuilder.kt | 0 .../store/sqlite/sql/WhereClauseBuilder.kt | 0 .../nip01Core/tags/addressables/ATag.kt | 0 .../nip01Core/tags/addressables/Address.kt | 37 +- .../nip01Core/tags/addressables/EventExt.kt | 0 .../tags/addressables/TagArrayBuilderExt.kt | 0 .../tags/addressables/TagArrayExt.kt | 0 .../quartz/nip01Core/tags/dTags/DTag.kt | 0 .../quartz/nip01Core/tags/dTags/EventExt.kt | 0 .../tags/dTags/TagArrayBuilderExt.kt | 0 .../nip01Core/tags/dTags/TagArrayExt.kt | 0 .../quartz/nip01Core/tags/events/ETag.kt | 0 .../quartz/nip01Core/tags/events/EventExt.kt | 0 .../nip01Core/tags/events/EventReference.kt | 0 .../nip01Core/tags/events/GenericETag.kt | 0 .../tags/events/TagArrayBuilderExt.kt | 0 .../nip01Core/tags/events/TagArrayExt.kt | 0 .../quartz/nip01Core/tags/geohash/EventExt.kt | 0 .../nip01Core/tags/geohash/GeoHashTag.kt | 0 .../tags/geohash/GeohashPrecision.kt | 0 .../tags/geohash/TagArrayBuilderExt.kt | 0 .../nip01Core/tags/geohash/TagArrayExt.kt | 0 .../nip01Core/tags/hashtags/EventExt.kt | 0 .../nip01Core/tags/hashtags/HashtagTag.kt | 0 .../nip01Core/tags/hashtags/MipMapHashTags.kt | 0 .../tags/hashtags/TagArrayBuilderExt.kt | 0 .../nip01Core/tags/hashtags/TagArrayExt.kt | 0 .../quartz/nip01Core/tags/kinds/EventExt.kt | 0 .../quartz/nip01Core/tags/kinds/KindTag.kt | 0 .../tags/kinds/TagArrayBuilderExt.kt | 0 .../nip01Core/tags/kinds/TagArrayExt.kt | 0 .../quartz/nip01Core/tags/people/EntityExt.kt | 0 .../quartz/nip01Core/tags/people/EventExt.kt | 0 .../quartz/nip01Core/tags/people/PTag.kt | 0 .../tags/people/PubKeyReferenceTag.kt | 0 .../tags/people/TagArrayBuilderExt.kt | 0 .../nip01Core/tags/people/TagArrayExt.kt | 0 .../tags/publishedAt/PublishedAtProvider.kt | 0 .../nip01Core/tags/references/EventExt.kt | 0 .../nip01Core/tags/references/ReferenceTag.kt | 0 .../tags/references/TagArrayBuilderExt.kt | 0 .../nip01Core/tags/references/TagArrayExt.kt | 0 .../nip02FollowList/ContactListEvent.kt | 0 .../nip02FollowList/ImmutableListOfLists.kt | 0 .../quartz/nip02FollowList/RelaySet.kt | 0 .../quartz/nip02FollowList/tags/ContactTag.kt | 0 .../quartz/nip03Timestamp/OtsEvent.kt | 0 .../quartz/nip03Timestamp/OtsResolver.kt | 12 +- .../nip03Timestamp/OtsResolverBuilder.kt | 0 .../nip03Timestamp/TagArrayBuilderExt.kt | 0 .../nip03Timestamp/VerificationState.kt | 0 .../nip03Timestamp/VerificationStateCache.kt | 0 .../nip03Timestamp/ots/BitcoinExplorer.kt | 43 ++ .../quartz/nip03Timestamp/ots/BlockHeader.kt | 29 + .../nip03Timestamp/ots/CalendarBuilder.kt | 30 + .../ots/DetachedTimestampFile.kt | 272 +++++++ .../quartz/nip03Timestamp/ots/Hash.kt | 170 +++++ .../quartz/nip03Timestamp/ots/ICalendar.kt | 39 ++ .../ots/ICalendarAsyncSubmit.kt | 29 + .../quartz/nip03Timestamp/ots/Merkle.kt | 118 ++++ .../nip03Timestamp/ots/OpenTimestamps.kt | 457 ++++++++++++ .../quartz/nip03Timestamp/ots/README.md | 0 .../ots/StreamDeserializationContext.kt | 112 +++ .../ots/StreamSerializationContext.kt | 84 +++ .../quartz/nip03Timestamp/ots/Timestamp.kt | 662 ++++++++++++++++++ .../quartz/nip03Timestamp/ots/Utils.kt | 166 +++++ .../quartz/nip03Timestamp/ots/VerifyResult.kt | 66 ++ .../BitcoinBlockHeaderAttestation.kt | 128 ++++ .../ots/attestation/PendingAttestation.kt | 141 ++++ .../ots/attestation/TimeAttestation.kt | 93 +++ .../ots/attestation/UnknownAttestation.kt | 82 +++ .../nip03Timestamp/ots/crypto/Digest.kt | 79 +++ .../ots/crypto/ExtendedDigest.kt | 31 + .../ots/crypto/GeneralDigest.kt | 174 +++++ .../nip03Timestamp/ots/crypto/KeccakDigest.kt | 551 +++++++++++++++ .../nip03Timestamp/ots/crypto/Memoable.kt | 50 ++ .../quartz/nip03Timestamp/ots/crypto/Pack.kt | 322 +++++++++ .../ots/crypto/RIPEMD160Digest.kt | 600 ++++++++++++++++ .../exceptions/CommitmentNotFoundException.kt | 25 + .../exceptions/DeserializationException.kt | 25 + .../ots/exceptions/ExceededSizeException.kt | 25 + .../ots/exceptions/UrlException.kt | 25 + .../ots/exceptions/VerificationException.kt | 25 + .../ots/http/BlockstreamExplorer.kt | 100 +++ .../nip03Timestamp/ots/http/Calendar.kt | 127 ++++ .../ots/http/CalendarAsyncSubmit.kt | 71 ++ .../ots/http/CalendarPureJavaBuilder.kt | 54 ++ .../quartz/nip03Timestamp/ots/http/Request.kt | 97 +++ .../nip03Timestamp/ots/http/Response.kt | 82 +++ .../ots/okhttp}/OkHttpBitcoinExplorer.kt | 9 +- .../ots/okhttp}/OkHttpCalendar.kt | 16 +- .../ots/okhttp}/OkHttpCalendarAsyncSubmit.kt | 5 +- .../ots/okhttp}/OkHttpCalendarBuilder.kt | 2 +- .../ots/okhttp}/OkHttpOtsResolverBuilder.kt | 24 +- .../ots/okhttp}/OtsBlockHeightCache.kt | 2 +- .../quartz/nip03Timestamp/ots/op/Op.kt | 162 +++++ .../quartz/nip03Timestamp/ots/op/OpAppend.kt | 60 ++ .../quartz/nip03Timestamp/ots/op/OpBinary.kt | 80 +++ .../quartz/nip03Timestamp/ots/op/OpCrypto.kt | 109 +++ .../nip03Timestamp/ots/op/OpKECCAK256.kt | 62 ++ .../quartz/nip03Timestamp/ots/op/OpPrepend.kt | 60 ++ .../nip03Timestamp/ots/op/OpRIPEMD160.kt | 63 ++ .../quartz/nip03Timestamp/ots/op/OpSHA1.kt | 61 ++ .../quartz/nip03Timestamp/ots/op/OpSHA256.kt | 55 ++ .../quartz/nip03Timestamp/ots/op/OpUnary.kt | 53 ++ .../nip03Timestamp/tags/TargetEventKindTag.kt | 0 .../nip03Timestamp/tags/TargetEventTag.kt | 0 .../quartz/nip04Dm/PrivateDMCache.kt | 0 .../quartz/nip04Dm/crypto/AESCBC.kt | 0 .../quartz/nip04Dm/crypto/EncryptedInfo.kt | 0 .../quartz/nip04Dm/crypto/Encryption.kt | 0 .../quartz/nip04Dm/crypto/Nip04.kt | 0 .../quartz/nip04Dm/messages/PrivateDmEvent.kt | 0 .../nip04Dm/messages/TagArrayBuilderExt.kt | 0 .../quartz/nip05DnsIdentifiers/Nip05.kt | 0 .../nip06KeyDerivation/Bip32SeedDerivation.kt | 0 .../quartz/nip06KeyDerivation/Bip39KeyPath.kt | 0 .../nip06KeyDerivation/Bip39Mnemonics.kt | 0 .../quartz/nip06KeyDerivation/Nip06.kt | 0 .../quartz/nip09Deletions/DeletionEvent.kt | 0 .../quartz/nip09Deletions/DeletionIndex.kt | 0 .../quartz/nip10Notes/BaseNoteEvent.kt | 0 .../quartz/nip10Notes/BaseThreadedEvent.kt | 0 .../quartz/nip10Notes/TextNoteEvent.kt | 0 .../nip10Notes/content/ContentHashTags.kt | 0 .../quartz/nip10Notes/content/IndexedTags.kt | 0 .../quartz/nip10Notes/content/NostrUris.kt | 0 .../quartz/nip10Notes/content/Urls.kt | 0 .../quartz/nip10Notes/tags/MarkedETag.kt | 0 .../quartz/nip10Notes/tags/Positional.kt | 0 .../quartz/nip10Notes/tags/ReplyBuilder.kt | 0 .../nip10Notes/tags/TagArrayBuilderExt.kt | 0 .../nip11RelayInfo/Nip11RelayInformation.kt | 0 .../vitorpamplona/quartz/nip13Pow/EventExt.kt | 0 .../quartz/nip13Pow/TagArrayBuilderExt.kt | 0 .../quartz/nip13Pow/TagArrayExt.kt | 0 .../quartz/nip13Pow/miner/ByteArrayExt.kt | 0 .../quartz/nip13Pow/miner/MiningBuffer.kt | 0 .../quartz/nip13Pow/miner/PoWMiner.kt | 0 .../quartz/nip13Pow/miner/PoWRankEvaluator.kt | 0 .../quartz/nip13Pow/tags/PoWTag.kt | 0 .../quartz/nip14Subject/EventExt.kt | 0 .../quartz/nip14Subject/SubjectTag.kt | 0 .../quartz/nip14Subject/TagArrayBuilderExt.kt | 0 .../quartz/nip14Subject/TagArrayExt.kt | 0 .../quartz/nip17Dm/NIP17Factory.kt | 0 .../quartz/nip17Dm/base/BaseDMGroupEvent.kt | 0 .../quartz/nip17Dm/base/ChatroomKey.kt | 0 .../quartz/nip17Dm/base/ChatroomKeyable.kt | 0 .../quartz/nip17Dm/base/NIP17Group.kt | 0 .../ChatMessageEncryptedFileHeaderEvent.kt | 0 .../nip17Dm/files/TagArrayBuilderExt.kt | 0 .../quartz/nip17Dm/files/encryption/AESGCM.kt | 0 .../nip17Dm/files/encryption/NostrCipher.kt | 0 .../nip17Dm/files/tags/EncryptionAlgo.kt | 0 .../nip17Dm/files/tags/EncryptionKey.kt | 0 .../nip17Dm/files/tags/EncryptionNonce.kt | 0 .../quartz/nip17Dm/files/tags/FileTypeTag.kt | 0 .../nip17Dm/messages/ChatMessageEvent.kt | 0 .../nip17Dm/messages/TagArrayBuilderExt.kt | 0 .../settings/ChatMessageRelayListEvent.kt | 0 .../quartz/nip17Dm/settings/tags/RelayTag.kt | 0 .../quartz/nip18Reposts/GenericRepostEvent.kt | 0 .../quartz/nip18Reposts/RepostEvent.kt | 0 .../quartz/nip18Reposts/quotes/EntityExt.kt | 0 .../quartz/nip18Reposts/quotes/EventExt.kt | 0 .../nip18Reposts/quotes/QAddressableTag.kt | 0 .../quartz/nip18Reposts/quotes/QEventTag.kt | 0 .../quartz/nip18Reposts/quotes/QTag.kt | 0 .../nip18Reposts/quotes/TagArrayBuilderExt.kt | 0 .../quartz/nip18Reposts/quotes/TagArrayExt.kt | 0 .../quartz/nip19Bech32/ATagExt.kt | 0 .../quartz/nip19Bech32/ByteArrayExt.kt | 0 .../quartz/nip19Bech32/EventExt.kt | 0 .../quartz/nip19Bech32/ListEntityExt.kt | 0 .../quartz/nip19Bech32/Nip19Parser.kt | 0 .../quartz/nip19Bech32/TlvBuilderExt.kt | 0 .../quartz/nip19Bech32/TlvTypes.kt | 0 .../quartz/nip19Bech32/bech32/Bech32Util.kt | 0 .../quartz/nip19Bech32/entities/Entity.kt | 0 .../quartz/nip19Bech32/entities/NAddress.kt | 0 .../quartz/nip19Bech32/entities/NEmbed.kt | 0 .../quartz/nip19Bech32/entities/NEvent.kt | 0 .../quartz/nip19Bech32/entities/NNote.kt | 0 .../quartz/nip19Bech32/entities/NProfile.kt | 0 .../quartz/nip19Bech32/entities/NPub.kt | 0 .../quartz/nip19Bech32/entities/NRelay.kt | 0 .../quartz/nip19Bech32/entities/NSec.kt | 0 .../quartz/nip19Bech32/tlv/Tlv.kt | 0 .../quartz/nip19Bech32/tlv/TlvBuilder.kt | 0 .../quartz/nip21UriScheme/EventExt.kt | 0 .../quartz/nip22Comments/CommentEvent.kt | 0 .../quartz/nip22Comments/RootScope.kt | 0 .../nip22Comments/TagArrayBuilderExt.kt | 0 .../nip22Comments/tags/ReplyAddressTag.kt | 0 .../nip22Comments/tags/ReplyAuthorTag.kt | 0 .../nip22Comments/tags/ReplyEventTag.kt | 0 .../nip22Comments/tags/ReplyIdentifierTag.kt | 0 .../quartz/nip22Comments/tags/ReplyKindTag.kt | 0 .../nip22Comments/tags/RootAddressTag.kt | 0 .../nip22Comments/tags/RootAuthorTag.kt | 0 .../quartz/nip22Comments/tags/RootEventTag.kt | 0 .../nip22Comments/tags/RootIdentifierTag.kt | 0 .../quartz/nip22Comments/tags/RootKindTag.kt | 0 .../nip23LongContent/LongTextNoteEvent.kt | 0 .../nip23LongContent/TagArrayBuilderExt.kt | 0 .../quartz/nip23LongContent/tags/ImageTag.kt | 0 .../nip23LongContent/tags/PublishedAtTag.kt | 0 .../nip23LongContent/tags/SummaryTag.kt | 0 .../quartz/nip23LongContent/tags/TitleTag.kt | 0 .../quartz/nip25Reactions/ReactionEvent.kt | 0 .../admin/ChannelCreateEvent.kt | 0 .../admin/ChannelHideMessageEvent.kt | 0 .../admin/ChannelMetadataEvent.kt | 0 .../admin/ChannelMuteUserEvent.kt | 0 .../base/BasePublicChatEvent.kt | 0 .../nip28PublicChat/base/ChannelData.kt | 0 .../base/IsInPublicChatChannel.kt | 0 .../base/TagArrayBuilderExt.kt | 0 .../nip28PublicChat/list/ChannelListEvent.kt | 0 .../list/TagArrayBuilderExt.kt | 0 .../nip28PublicChat/list/TagArrayExt.kt | 0 .../nip28PublicChat/list/tags/ChannelTag.kt | 0 .../message/ChannelMessageEvent.kt | 0 .../quartz/nip30CustomEmoji/CustomEmoji.kt | 0 .../quartz/nip30CustomEmoji/EmojiUrlTag.kt | 0 .../quartz/nip30CustomEmoji/EventExt.kt | 0 .../nip30CustomEmoji/TagArrayBuilderExt.kt | 0 .../quartz/nip30CustomEmoji/TagArrayExt.kt | 0 .../nip30CustomEmoji/pack/EmojiPackEvent.kt | 0 .../selection/EmojiPackSelectionEvent.kt | 0 .../selection/TagArrayBuilderExt.kt | 0 .../vitorpamplona/quartz/nip31Alts/AltTag.kt | 0 .../quartz/nip31Alts/EventExt.kt | 0 .../quartz/nip31Alts/TagArrayBuilderExt.kt | 0 .../quartz/nip31Alts/TagArrayExt.kt | 0 .../quartz/nip34Git/issue/GitIssueEvent.kt | 0 .../nip34Git/issue/TagArrayBuilderExt.kt | 0 .../quartz/nip34Git/patch/GitPatchEvent.kt | 0 .../quartz/nip34Git/reply/GitReplyEvent.kt | 0 .../nip34Git/reply/TagArrayBuilderExt.kt | 0 .../nip34Git/repository/GitRepositoryEvent.kt | 0 .../nip34Git/repository/TagArrayBuilderExt.kt | 0 .../nip34Git/repository/tags/CloneTag.kt | 0 .../repository/tags/DescriptionTag.kt | 0 .../nip34Git/repository/tags/NameTag.kt | 0 .../quartz/nip34Git/repository/tags/WebTag.kt | 0 .../quartz/nip35Torrents/DefaultTrackers.kt | 0 .../nip35Torrents/TagArrayBuilderExt.kt | 0 .../nip35Torrents/TorrentCommentEvent.kt | 0 .../quartz/nip35Torrents/TorrentEvent.kt | 0 .../quartz/nip35Torrents/tags/BtihTag.kt | 0 .../quartz/nip35Torrents/tags/FileTag.kt | 0 .../quartz/nip35Torrents/tags/InfoHashTag.kt | 0 .../quartz/nip35Torrents/tags/TrackerTag.kt | 0 .../ContentWarningTag.kt | 0 .../quartz/nip36SensitiveContent/EventExt.kt | 0 .../TagArrayBuilderExt.kt | 0 .../nip36SensitiveContent/TagArrayExt.kt | 0 .../quartz/nip37Drafts/DraftWrapCache.kt | 0 .../quartz/nip37Drafts/DraftWrapEvent.kt | 0 .../quartz/nip37Drafts/ExposeInDraft.kt | 0 .../PrivateOutboxRelayListEvent.kt | 0 .../quartz/nip38UserStatus/StatusEvent.kt | 0 .../quartz/nip39ExtIdentities/EventExt.kt | 0 .../nip39ExtIdentities/GitHubIdentity.kt | 0 .../nip39ExtIdentities/IdentityClaimTag.kt | 0 .../nip39ExtIdentities/MastodonIdentity.kt | 0 .../nip39ExtIdentities/TagArrayBuilderExt.kt | 0 .../nip39ExtIdentities/TelegramIdentity.kt | 0 .../nip39ExtIdentities/TwitterIdentity.kt | 0 .../nip39ExtIdentities/UnsupportedIdentity.kt | 0 .../quartz/nip40Expiration/EventExt.kt | 0 .../quartz/nip40Expiration/ExpirationTag.kt | 0 .../nip40Expiration/TagArrayBuilderExt.kt | 0 .../quartz/nip40Expiration/TagArrayExt.kt | 0 .../quartz/nip42RelayAuth/RelayAuthEvent.kt | 0 .../nip42RelayAuth/tags/ChallengeTag.kt | 0 .../quartz/nip42RelayAuth/tags/RelayTag.kt | 0 .../nip44Encryption/EncryptedInfoString.kt | 0 .../quartz/nip44Encryption/Nip44.kt | 0 .../quartz/nip44Encryption/Nip44v1.kt | 0 .../quartz/nip44Encryption/Nip44v2.kt | 0 .../quartz/nip44Encryption/SharedKeyCache.kt | 0 .../quartz/nip44Encryption/crypto/Hkdf.kt | 0 .../quartz/nip46RemoteSigner/BunkerMessage.kt | 0 .../quartz/nip46RemoteSigner/BunkerRequest.kt | 0 .../nip46RemoteSigner/BunkerRequestConnect.kt | 0 .../BunkerRequestGetPublicKey.kt | 0 .../BunkerRequestGetRelays.kt | 0 .../BunkerRequestNip04Decrypt.kt | 0 .../BunkerRequestNip04Encrypt.kt | 0 .../BunkerRequestNip44Decrypt.kt | 0 .../BunkerRequestNip44Encrypt.kt | 0 .../nip46RemoteSigner/BunkerRequestPing.kt | 0 .../nip46RemoteSigner/BunkerRequestSign.kt | 0 .../nip46RemoteSigner/BunkerResponse.kt | 0 .../nip46RemoteSigner/BunkerResponseAck.kt | 0 .../BunkerResponseDecrypt.kt | 0 .../BunkerResponseEncrypt.kt | 0 .../nip46RemoteSigner/BunkerResponseError.kt | 0 .../nip46RemoteSigner/BunkerResponseEvent.kt | 0 .../BunkerResponseGetRelays.kt | 0 .../nip46RemoteSigner/BunkerResponsePong.kt | 0 .../BunkerResponsePublicKey.kt | 0 .../nip46RemoteSigner/NostrConnectEvent.kt | 0 .../LnZapPaymentRequestEvent.kt | 0 .../LnZapPaymentResponseEvent.kt | 0 .../nip47WalletConnect/Nip47WalletConnect.kt | 0 .../NostrWalletConnectRequestCache.kt | 0 .../NostrWalletConnectResponseCache.kt | 0 .../quartz/nip47WalletConnect/Request.kt | 0 .../nip47WalletConnect/RequestDeserializer.kt | 0 .../quartz/nip47WalletConnect/Response.kt | 0 .../ResponseDeserializer.kt | 0 .../quartz/nip48ProxyTags/EventExt.kt | 0 .../quartz/nip48ProxyTags/ProxyTag.kt | 0 .../nip48ProxyTags/TagArrayBuilderExt.kt | 0 .../quartz/nip48ProxyTags/TagArrayExt.kt | 0 .../quartz/nip49PrivKeyEnc/ByteArrayExt.kt | 0 .../quartz/nip49PrivKeyEnc/Nip49.kt | 0 .../quartz/nip49PrivKeyEnc/PBKDF.java | 0 .../quartz/nip49PrivKeyEnc/SCrypt.java | 0 .../nip49PrivKeyEnc/SecretKeyOrEmptySpec.java | 0 .../nip50Search/SearchRelayListEvent.kt | 0 .../quartz/nip50Search/SearchableEvent.kt | 0 .../quartz/nip51Lists/PinListEvent.kt | 0 .../nip51Lists/PrivateTagArrayBuilder.kt | 0 .../quartz/nip51Lists/PrivateTagArrayEvent.kt | 0 .../nip51Lists/PrivateTagArrayEventCache.kt | 0 .../quartz/nip51Lists/TagArrayExt.kt | 0 .../bookmarkList/BookmarkListEvent.kt | 0 .../bookmarkList/TagArrayBuilderExt.kt | 0 .../bookmarkList/tags/AddressBookmark.kt | 0 .../bookmarkList/tags/BookmarkIdTag.kt | 0 .../bookmarkList/tags/EventBookmark.kt | 0 .../nip51Lists/encryption/NostrSignerExt.kt | 0 .../encryption/PrivateTagsInContent.kt | 0 .../nip51Lists/followList/FollowListEvent.kt | 0 .../followList/TagArrayBuilderExt.kt | 0 .../nip51Lists/followList/TagArrayExt.kt | 0 .../geohashList/GeohashListEvent.kt | 0 .../geohashList/TagArrayBuilderExt.kt | 0 .../nip51Lists/geohashList/TagArrayExt.kt | 0 .../hashtagList/HashtagListEvent.kt | 0 .../hashtagList/TagArrayBuilderExt.kt | 0 .../nip51Lists/hashtagList/TagArrayExt.kt | 0 .../nip51Lists/muteList/MuteListEvent.kt | 0 .../nip51Lists/muteList/TagArrayBuilderExt.kt | 0 .../quartz/nip51Lists/muteList/TagArrayExt.kt | 0 .../nip51Lists/muteList/tags/MuteTag.kt | 0 .../nip51Lists/muteList/tags/UserTag.kt | 0 .../nip51Lists/muteList/tags/WordTag.kt | 0 .../nip51Lists/peopleList/PeopleListEvent.kt | 0 .../peopleList/TagArrayBuilderExt.kt | 0 .../nip51Lists/peopleList/TagArrayExt.kt | 0 .../relayLists/BlockedRelayListEvent.kt | 0 .../relayLists/BroadcastRelayListEvent.kt | 0 .../relayLists/IndexerRelayListEvent.kt | 0 .../relayLists/ProxyRelayListEvent.kt | 0 .../relayLists/TrustedRelayListEvent.kt | 0 .../nip51Lists/relayLists/tags/RelayTag.kt | 0 .../relayLists/tags/TagArrayBuilderExt.kt | 0 .../nip51Lists/relayLists/tags/TagArrayExt.kt | 0 .../nip51Lists/relaySets/RelaySetEvent.kt | 0 .../quartz/nip51Lists/tags/DescriptionTag.kt | 0 .../quartz/nip51Lists/tags/ImageTag.kt | 0 .../quartz/nip51Lists/tags/NameTag.kt | 0 .../quartz/nip51Lists/tags/RelayTag.kt | 0 .../quartz/nip51Lists/tags/TitleTag.kt | 0 .../nip52Calendar/CalendarDateSlotEvent.kt | 0 .../quartz/nip52Calendar/CalendarEvent.kt | 0 .../quartz/nip52Calendar/CalendarRSVPEvent.kt | 0 .../nip52Calendar/CalendarTimeSlotEvent.kt | 0 .../chat/LiveActivitiesChatMessageEvent.kt | 0 .../chat/TagArrayBuilderExt.kt | 0 .../streaming/LiveActivitiesEvent.kt | 0 .../streaming/tags/CurrentParticipantsTag.kt | 0 .../streaming/tags/EndsTag.kt | 0 .../streaming/tags/ParticipantTag.kt | 0 .../streaming/tags/RelayListTag.kt | 0 .../streaming/tags/StartsTag.kt | 0 .../streaming/tags/StatusTag.kt | 0 .../streaming/tags/StreamingTag.kt | 0 .../streaming/tags/TotalParticipantsTag.kt | 0 .../quartz/nip54Wiki/WikiNoteEvent.kt | 0 .../quartz/nip55AndroidSigner/SignString.kt | 0 .../nip55AndroidSigner/api/CommandType.kt | 0 .../nip55AndroidSigner/api/SignerResult.kt | 0 .../api/background/queries/DecryptZapQuery.kt | 0 .../api/background/queries/DeriveKeyQuery.kt | 0 .../api/background/queries/LoginQuery.kt | 0 .../background/queries/Nip04DecryptQuery.kt | 0 .../background/queries/Nip04EncryptQuery.kt | 0 .../background/queries/Nip44DecryptQuery.kt | 0 .../background/queries/Nip44EncryptQuery.kt | 0 .../api/background/queries/SignQuery.kt | 0 .../background/utils/ContentResolverExt.kt | 0 .../api/background/utils/CursorExt.kt | 0 .../api/foreground/IntentRequestManager.kt | 0 .../intents/requests/DecryptZapRequest.kt | 0 .../intents/requests/DeriveKeyRequest.kt | 0 .../intents/requests/LoginRequest.kt | 0 .../intents/requests/Nip04DecryptRequest.kt | 0 .../intents/requests/Nip04EncryptRequest.kt | 0 .../intents/requests/Nip44DecryptRequest.kt | 0 .../intents/requests/Nip44EncryptRequest.kt | 0 .../intents/requests/SignRequest.kt | 0 .../intents/responses/DecryptZapResponse.kt | 0 .../intents/responses/DeriveKeyResponse.kt | 0 .../intents/responses/LoginResponse.kt | 0 .../intents/responses/Nip04DecryptResponse.kt | 0 .../intents/responses/Nip04EncryptResponse.kt | 0 .../intents/responses/Nip44DecryptResponse.kt | 0 .../intents/responses/Nip44EncryptResponse.kt | 0 .../intents/responses/SignResponse.kt | 0 .../intents/results/IntentResult.kt | 0 .../results/IntentResultJsonDeserializer.kt | 0 .../results/IntentResultJsonSerializer.kt | 0 .../api/permission/Permission.kt | 0 .../api/permission/PermissionDeserializer.kt | 0 .../api/permission/PermissionSerializer.kt | 0 .../client/ExternalSignerLogin.kt | 0 .../client/IActivityLauncher.kt | 0 .../client/IsExternalSignerInstalled.kt | 0 .../client/NostrSignerExternal.kt | 0 .../handlers/BackgroundRequestHandler.kt | 0 .../handlers/ForegroundRequestHandler.kt | 0 .../quartz/nip56Reports/ReportEvent.kt | 0 .../quartz/nip56Reports/ReportType.kt | 0 .../quartz/nip56Reports/TagArrayBuilderExt.kt | 0 .../quartz/nip56Reports/tags/BaseReportTag.kt | 0 .../nip56Reports/tags/DefaultReportTag.kt | 0 .../quartz/nip56Reports/tags/HashSha256Tag.kt | 0 .../nip56Reports/tags/ReportedAddressTag.kt | 0 .../nip56Reports/tags/ReportedAuthorTag.kt | 0 .../nip56Reports/tags/ReportedEventTag.kt | 0 .../quartz/nip56Reports/tags/ServerTag.kt | 0 .../quartz/nip57Zaps/LnZapEvent.kt | 0 .../quartz/nip57Zaps/LnZapEventInterface.kt | 0 .../quartz/nip57Zaps/LnZapPrivateEvent.kt | 0 .../quartz/nip57Zaps/LnZapRequestEvent.kt | 0 .../quartz/nip57Zaps/PrivateZapCache.kt | 0 .../quartz/nip57Zaps/PrivateZapEncryption.kt | 0 .../nip57Zaps/PrivateZapRequestBuilder.kt | 0 .../nip57Zaps/splits/BaseZapSplitSetup.kt | 0 .../quartz/nip57Zaps/splits/EventExt.kt | 0 .../nip57Zaps/splits/TagArrayBuilderExt.kt | 0 .../quartz/nip57Zaps/splits/TagArrayExt.kt | 0 .../quartz/nip57Zaps/splits/ZapSplitSetup.kt | 0 .../splits/ZapSplitSetupLnAddress.kt | 0 .../nip57Zaps/splits/ZapSplitSetupParser.kt | 0 .../splits/ZapSplitSetupSerializer.kt | 0 .../quartz/nip57Zaps/zapraiser/EventExt.kt | 0 .../nip57Zaps/zapraiser/TagArrayBuilderExt.kt | 0 .../quartz/nip57Zaps/zapraiser/TagArrayExt.kt | 0 .../nip57Zaps/zapraiser/ZapRaiserTag.kt | 0 .../quartz/nip58Badges/BadgeAwardEvent.kt | 0 .../nip58Badges/BadgeDefinitionEvent.kt | 0 .../quartz/nip58Badges/BadgeProfilesEvent.kt | 0 .../quartz/nip59Giftwrap/HostStub.kt | 0 .../quartz/nip59Giftwrap/WrappedEvent.kt | 0 .../quartz/nip59Giftwrap/rumors/Rumor.kt | 0 .../nip59Giftwrap/rumors/RumorAssembler.kt | 0 .../nip59Giftwrap/rumors/RumorDeserializer.kt | 0 .../nip59Giftwrap/rumors/RumorSerializer.kt | 0 .../nip59Giftwrap/seals/SealedRumorEvent.kt | 0 .../nip59Giftwrap/wraps/GiftWrapEvent.kt | 0 .../RequestToVanishEvent.kt | 0 .../nip62RequestToVanish/tags/RelayTag.kt | 0 .../tags/TagArrayBuilderExt.kt | 0 .../nip62RequestToVanish/tags/TagArrayExt.kt | 0 .../AdvertisedRelayListEvent.kt | 0 .../RelayListRecommendationProcessor.kt | 0 .../tags/AdvertisedRelayInfoTag.kt | 0 .../quartz/nip68Picture/IMetaTagBuilderExt.kt | 0 .../quartz/nip68Picture/IMetaTagExt.kt | 0 .../quartz/nip68Picture/PictureEvent.kt | 0 .../quartz/nip68Picture/PictureMeta.kt | 0 .../quartz/nip68Picture/TagArrayBuilderExt.kt | 0 .../quartz/nip68Picture/tags/LocationTag.kt | 0 .../nip68Picture/tags/UserAnnotationTag.kt | 0 .../quartz/nip70ProtectedEvts/EventExt.kt | 0 .../nip70ProtectedEvts/TagArrayBuilderExt.kt | 0 .../quartz/nip70ProtectedEvts/TagArrayExt.kt | 0 .../nip70ProtectedEvts/tags/ProtectedTag.kt | 0 .../quartz/nip71Video/IMetaTagBuilderExt.kt | 0 .../quartz/nip71Video/IMetaTagExt.kt | 0 .../quartz/nip71Video/TagArrayBuilderExt.kt | 0 .../quartz/nip71Video/VideoEvent.kt | 0 .../quartz/nip71Video/VideoHorizontalEvent.kt | 0 .../quartz/nip71Video/VideoMeta.kt | 0 .../quartz/nip71Video/VideoNormalEvent.kt | 0 .../quartz/nip71Video/VideoShortEvent.kt | 0 .../quartz/nip71Video/VideoVerticalEvent.kt | 0 .../quartz/nip71Video/tags/DurationTag.kt | 0 .../quartz/nip71Video/tags/SegmentTag.kt | 0 .../quartz/nip71Video/tags/TextTrackTag.kt | 0 .../quartz/nip72ModCommunities/EventExt.kt | 0 .../approval/CommunityPostApprovalEvent.kt | 0 .../approval/TagArrayBuilderExt.kt | 0 .../approval/tags/ApprovedAddressTag.kt | 0 .../approval/tags/ApprovedEventTag.kt | 0 .../definition/CommunityDefinitionEvent.kt | 0 .../definition/TagArrayBuilderExt.kt | 0 .../definition/tags/DescriptionTag.kt | 0 .../definition/tags/ImageTag.kt | 0 .../definition/tags/ModeratorTag.kt | 0 .../definition/tags/NameTag.kt | 0 .../definition/tags/RelayTag.kt | 0 .../definition/tags/RulesTag.kt | 0 .../follow/CommunityListEvent.kt | 0 .../follow/TagArrayBuilderExt.kt | 0 .../nip72ModCommunities/follow/TagArrayExt.kt | 0 .../follow/tags/CommunityTag.kt | 0 .../nip73ExternalIds/CommentEventExt.kt | 0 .../quartz/nip73ExternalIds/ExternalId.kt | 0 .../quartz/nip73ExternalIds/books/BookId.kt | 0 .../nip73ExternalIds/books/CommentEventExt.kt | 0 .../location/CommentEventExt.kt | 0 .../nip73ExternalIds/location/GeohashId.kt | 0 .../movies/CommentEventExt.kt | 0 .../quartz/nip73ExternalIds/movies/MovieId.kt | 0 .../papers/CommentEventExt.kt | 0 .../quartz/nip73ExternalIds/papers/PaperId.kt | 0 .../podcasts/CommentEventExt.kt | 0 .../podcasts/PodcastEpisodeId.kt | 0 .../podcasts/PodcastFeedId.kt | 0 .../podcasts/PodcastPublisherId.kt | 0 .../topics/CommentEventExt.kt | 0 .../nip73ExternalIds/topics/HashtagId.kt | 0 .../nip73ExternalIds/urls/CommentEventExt.kt | 0 .../quartz/nip73ExternalIds/urls/UrlId.kt | 0 .../quartz/nip75ZapGoals/GoalEvent.kt | 0 .../nip75ZapGoals/TagArrayBuilderExt.kt | 0 .../quartz/nip75ZapGoals/tags/AmountTag.kt | 0 .../quartz/nip75ZapGoals/tags/ClosedAtTag.kt | 0 .../quartz/nip75ZapGoals/tags/RelayListTag.kt | 0 .../nip78AppData/AppSpecificDataEvent.kt | 0 .../quartz/nip84Highlights/HighlightEvent.kt | 0 .../quartz/nip84Highlights/tags/CommentTag.kt | 0 .../quartz/nip84Highlights/tags/ContextTag.kt | 0 .../quartz/nip89AppHandlers/PlatformType.kt | 0 .../nip89AppHandlers/clientTag/ClientTag.kt | 0 .../nip89AppHandlers/clientTag/EventExt.kt | 0 .../clientTag/TagArrayBuilderExt.kt | 0 .../nip89AppHandlers/clientTag/TagArrayExt.kt | 0 .../definition/AppDefinitionEvent.kt | 0 .../definition/AppMetadata.kt | 0 .../nip89AppHandlers/definition/EntityType.kt | 0 .../definition/TagArrayBuilderExt.kt | 0 .../definition/tags/PlatformLinkTag.kt | 0 .../recommendation/AppRecommendationEvent.kt | 0 .../recommendation/TagArrayBuilderExt.kt | 0 .../recommendation/tags/RecommendationTag.kt | 0 .../NIP90ContentDiscoveryRequestEvent.kt | 0 .../NIP90ContentDiscoveryResponseEvent.kt | 0 .../quartz/nip90Dvms/NIP90StatusEvent.kt | 0 .../NIP90UserDiscoveryRequestEvent.kt | 0 .../NIP90UserDiscoveryResponseEvent.kt | 0 .../quartz/nip92IMeta/EventExt.kt | 0 .../quartz/nip92IMeta/IMetaTag.kt | 0 .../quartz/nip92IMeta/IMetaTagBuilder.kt | 0 .../quartz/nip92IMeta/TagArrayBuilderExt.kt | 0 .../quartz/nip92IMeta/TagArrayExt.kt | 0 .../nip94FileMetadata/FileHeaderEvent.kt | 0 .../nip94FileMetadata/IMetaTagBuilderExt.kt | 0 .../nip94FileMetadata/TagArrayBuilderExt.kt | 0 .../nip94FileMetadata/tags/BlurhashTag.kt | 0 .../nip94FileMetadata/tags/DimensionTag.kt | 0 .../nip94FileMetadata/tags/FallbackTag.kt | 0 .../nip94FileMetadata/tags/HashSha256Tag.kt | 0 .../quartz/nip94FileMetadata/tags/ImageTag.kt | 0 .../nip94FileMetadata/tags/MagnetTag.kt | 0 .../nip94FileMetadata/tags/MimeTypeTag.kt | 0 .../nip94FileMetadata/tags/OriginalHashTag.kt | 0 .../nip94FileMetadata/tags/ServiceTag.kt | 0 .../quartz/nip94FileMetadata/tags/SizeTag.kt | 0 .../nip94FileMetadata/tags/SummaryTag.kt | 0 .../quartz/nip94FileMetadata/tags/ThumbTag.kt | 0 .../nip94FileMetadata/tags/TorrentInfoHash.kt | 0 .../quartz/nip94FileMetadata/tags/UrlTag.kt | 0 .../nip96FileStorage/HttpUrlFormatter.kt | 0 .../nip96FileStorage/actions/DeleteResult.kt | 0 .../nip96FileStorage/actions/UploadResult.kt | 0 .../config/FileServersEvent.kt | 0 .../config/TagArrayBuilderExt.kt | 0 .../nip96FileStorage/config/tags/ServerTag.kt | 0 .../nip96FileStorage/info/ServerInfo.kt | 0 .../nip96FileStorage/info/ServerInfoParser.kt | 0 .../nip98HttpAuth/HTTPAuthorizationEvent.kt | 0 .../nip98HttpAuth/TagArrayBuilderExt.kt | 0 .../quartz/nip98HttpAuth/tags/MethodTag.kt | 0 .../nip98HttpAuth/tags/PayloadHashTag.kt | 0 .../quartz/nip98HttpAuth/tags/UrlTag.kt | 0 .../nip99Classifieds/ClassifiedsEvent.kt | 0 .../nip99Classifieds/ProductImageMeta.kt | 0 .../nip99Classifieds/TagArrayBuilderExt.kt | 0 .../nip99Classifieds/tags/ConditionTag.kt | 0 .../nip99Classifieds/tags/LocationTag.kt | 0 .../quartz/nip99Classifieds/tags/PriceTag.kt | 0 .../quartz/nip99Classifieds/tags/StatusTag.kt | 0 .../quartz/nipA0VoiceMessages/AudioMeta.kt | 0 .../nipA0VoiceMessages/BaseVoiceEvent.kt | 0 .../nipA0VoiceMessages/IMetaTagBuilderExt.kt | 0 .../quartz/nipA0VoiceMessages/IMetaTagExt.kt | 0 .../nipA0VoiceMessages/TagArrayBuilderExt.kt | 0 .../quartz/nipA0VoiceMessages/VoiceEvent.kt | 0 .../nipA0VoiceMessages/VoiceReplyEvent.kt | 0 .../nipA0VoiceMessages/tags/DurationTag.kt | 0 .../nipA0VoiceMessages/tags/HashSha256Tag.kt | 0 .../nipA0VoiceMessages/tags/MimeTypeTag.kt | 0 .../nipA0VoiceMessages/tags/ReplyAuthorTag.kt | 0 .../nipA0VoiceMessages/tags/ReplyEventTag.kt | 0 .../nipA0VoiceMessages/tags/ReplyKindTag.kt | 0 .../nipA0VoiceMessages/tags/WaveformTag.kt | 0 .../nipB7Blossom/BlossomAuthorizationEvent.kt | 0 .../nipB7Blossom/BlossomServersEvent.kt | 0 .../vitorpamplona/quartz/utils/ArrayUtils.kt | 0 .../quartz/utils/CacheCollectors.kt | 0 .../quartz/utils/CacheOperations.kt | 0 .../com/vitorpamplona/quartz/utils/Ensure.kt | 0 .../com/vitorpamplona/quartz/utils/GZip.kt | 0 .../com/vitorpamplona/quartz/utils/Hex.kt | 0 .../com/vitorpamplona/quartz/utils/Hmac512.kt | 0 .../vitorpamplona/quartz/utils/IterableExt.kt | 0 .../vitorpamplona/quartz/utils/LargeCache.kt | 0 .../quartz/utils/LargeSoftCache.kt | 0 .../quartz/utils/LibSodiumInstance.kt | 0 .../quartz/utils/MapOfSetBuilder.kt | 0 .../quartz/utils/ParallelUtils.kt | 0 .../quartz/utils/RandomInstance.kt | 0 .../quartz/utils/Secp256k1Instance.kt | 0 .../vitorpamplona/quartz/utils/StringUtils.kt | 0 .../vitorpamplona/quartz/utils/TimeUtils.kt | 0 .../quartz/utils/UriReferenceExt.kt | 0 .../quartz/utils/sha256/Sha256.kt | 0 .../quartz/utils/sha256/Sha256Hasher.kt | 0 .../quartz/utils/sha256/Sha256Pool.kt | 0 .../com/vitorpamplona/quartz/Platform.kt | 23 + .../com/vitorpamplona/quartz/Platform.ios.kt | 23 + quartz/src/main/AndroidManifest.xml | 4 - .../nip03Timestamp/ots/BitcoinExplorer.java | 21 - .../nip03Timestamp/ots/BlockHeader.java | 73 -- .../ots/BlockstreamExplorer.java | 66 -- .../quartz/nip03Timestamp/ots/Calendar.java | 123 ---- .../ots/CalendarAsyncSubmit.java | 56 -- .../nip03Timestamp/ots/CalendarBuilder.java | 6 - .../ots/CalendarPureJavaBuilder.java | 10 - .../ots/DetachedTimestampFile.java | 227 ------ .../quartz/nip03Timestamp/ots/Hash.java | 202 ------ .../quartz/nip03Timestamp/ots/ICalendar.java | 13 - .../ots/ICalendarAsyncSubmit.java | 9 - .../quartz/nip03Timestamp/ots/Merkle.java | 95 --- .../nip03Timestamp/ots/OpenTimestamps.java | 485 ------------- .../ots/StreamDeserializationContext.java | 107 --- .../ots/StreamSerializationContext.java | 81 --- .../quartz/nip03Timestamp/ots/Timestamp.java | 627 ----------------- .../quartz/nip03Timestamp/ots/Utils.java | 205 ------ .../nip03Timestamp/ots/VerifyResult.java | 59 -- .../BitcoinBlockHeaderAttestation.java | 117 ---- .../EthereumBlockHeaderAttestation.java | 77 -- .../LitecoinBlockHeaderAttestation.java | 98 --- .../ots/attestation/PendingAttestation.java | 133 ---- .../ots/attestation/TimeAttestation.java | 83 --- .../ots/attestation/UnknownAttestation.java | 75 -- .../nip03Timestamp/ots/crypto/Digest.java | 52 -- .../ots/crypto/ExtendedDigest.java | 11 - .../ots/crypto/GeneralDigest.java | 138 ---- .../ots/crypto/KeccakDigest.java | 473 ------------- .../nip03Timestamp/ots/crypto/Memoable.java | 28 - .../nip03Timestamp/ots/crypto/Pack.java | 242 ------- .../ots/crypto/RIPEMD160Digest.java | 442 ------------ .../CommitmentNotFoundException.java | 7 - .../exceptions/DeserializationException.java | 7 - .../ots/exceptions/ExceededSizeException.java | 7 - .../ots/exceptions/UrlException.java | 7 - .../ots/exceptions/VerificationException.java | 7 - .../nip03Timestamp/ots/http/Request.java | 92 --- .../nip03Timestamp/ots/http/Response.java | 77 -- .../quartz/nip03Timestamp/ots/op/Op.java | 137 ---- .../nip03Timestamp/ots/op/OpAppend.java | 62 -- .../nip03Timestamp/ots/op/OpBinary.java | 76 -- .../nip03Timestamp/ots/op/OpCrypto.java | 97 --- .../nip03Timestamp/ots/op/OpKECCAK256.java | 59 -- .../nip03Timestamp/ots/op/OpPrepend.java | 63 -- .../nip03Timestamp/ots/op/OpRIPEMD160.java | 64 -- .../quartz/nip03Timestamp/ots/op/OpSHA1.java | 65 -- .../nip03Timestamp/ots/op/OpSHA256.java | 59 -- .../quartz/nip03Timestamp/ots/op/OpUnary.java | 43 -- quartz/src/test/java/android/util/Log.java | 35 - 979 files changed, 6285 insertions(+), 5706 deletions(-) delete mode 100644 quartz/build.gradle create mode 100644 quartz/build.gradle.kts delete mode 100644 quartz/notebooks/Kind1Test.ipynb rename quartz/src/{androidTest => androidDeviceTest}/AndroidManifest.xml (100%) rename quartz/src/{androidTest => androidDeviceTest}/assets/bip39.vectors.json (100%) rename quartz/src/{androidTest => androidDeviceTest}/assets/github_amethyst.html (100%) rename quartz/src/{androidTest => androidDeviceTest}/assets/nip44.vectors.json (100%) rename quartz/src/{androidTest => androidDeviceTest}/assets/nostr_vitor_short.json (100%) rename quartz/src/{androidTest => androidDeviceTest}/assets/nostr_vitor_startup_data.json (100%) rename quartz/src/{androidTest => androidDeviceTest}/assets/ovxxk2vz.jpg (100%) rename quartz/src/{androidTest => androidDeviceTest}/assets/relayDB.txt (100%) rename quartz/src/{androidTest => androidDeviceTest}/assets/trouble_video (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/LargeDBSignatureCheck.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/bloom/BloomFilter.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/lightning/LnInvoiceUtilTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip01Core/EventSigCheck.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip01Core/Nip01Test.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip01Core/crypto/Nip01CryptoTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/AddressableTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/AssertUtils.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/BasicTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/DeletionTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/ExpirationTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/LargeDBTests.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/ReplaceableTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/RightToVanishTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/SearchTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip03Timestamp/ots/OtsTest.kt (96%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip04Dm/EncryptionTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip04Dm/Nip04Test.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip06KeyDerivation/Bip32SeedDerivationTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39KeyPathTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39MnemonicsTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip06KeyDerivation/Nip06Test.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip10Notes/CitationTests.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip10Notes/ThreadingTests.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip13Pow/PoWMinerTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip13Pow/PoWRankEvaluatorTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip17Dm/AESGCMTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip17Dm/ChatroomKeyTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip19Bech32/NIP19EmbedTests.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip22Comments/GeolocatedComments.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip44Encryption/Nip44v1Test.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip44Encryption/Nip44v2Test.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip44Encryption/TestPackageClasses.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/Nip46Test.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip49PrivKeyEnc/NIP49Test.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/SignStringTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip57Zaps/PrivateZapTests.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/nip59GiftWraps/GiftWrapEventTest.kt (100%) rename quartz/src/{androidTest/java => androidDeviceTest/kotlin}/com/vitorpamplona/quartz/utils/HexEncodingTest.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/lightning/Lud06Test.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip01Core/hints/BloomFilterMurMur3Test.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip01Core/hints/HintIndexerTest.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip01Core/hints/MurMur3Test.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip01Core/hints/relayDB.txt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip01Core/jackson/EventDeserializerTest.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip01Core/jackson/InliningTagArrayPrettyPrinterTest.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip01Core/metadata/UpdateMetadataTest.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/RelayUrlFormatterTest.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/EventDbQueryAssemblerTest.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip05DnsIdentifiers/Nip05Test.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip19Bech32/NIP19ParserTest.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip19Bech32/TlvIntegerTest.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip30CustomEmoji/Nip30Test.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestTest.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip51Lists/TagArrayExt.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip65RelayList/RelayListRecommendationProcessorTest.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/nip96FileStorage/Nip96Test.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/utils/HexEncodingTest.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/utils/RuntimeExt.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/utils/SignerUtils.kt (100%) rename quartz/src/{test/java => androidHostTest/kotlin}/com/vitorpamplona/quartz/utils/StringUtilsTest.kt (100%) create mode 100644 quartz/src/androidMain/AndroidManifest.xml rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/EventFactory.kt (100%) create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/Platform.android.kt rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/audio/header/AudioHeaderEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/audio/header/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/audio/header/tags/DownloadUrlTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/audio/header/tags/StreamUrlTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/audio/header/tags/WaveformTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/audio/track/AudioTrackEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/audio/track/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/audio/track/tags/CoverTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/audio/track/tags/MediaTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/audio/track/tags/ParticipantTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/audio/track/tags/PriceTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/audio/track/tags/TypeTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/bounties/BountyAddValueEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/bounties/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/bounties/RewardTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/bounties/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/decoupling/DecoupledCipher.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/decoupling/EncryptionKeyCache.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/decoupling/EncryptionKeyDerivation.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/decoupling/setup/EncryptionKeyListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/decoupling/setup/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/decoupling/setup/tags/KeyTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/edits/TextNoteModificationEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/ephemChat/chat/EphemeralChatEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/ephemChat/chat/RoomId.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/ephemChat/chat/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/ephemChat/chat/tags/RelayTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/ephemChat/chat/tags/RoomTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/ephemChat/db/EphemeralRoom.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/ephemChat/db/EphemeralRoomCache.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/ephemChat/list/EphemeralChatListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/ephemChat/list/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/ephemChat/list/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/ephemChat/list/tags/RoomIdTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/forks/BaseThreadedEventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/forks/MarkedETagExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/inlineMetadata/Nip54InlineMetadata.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStoryBaseEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStoryPrologueEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStoryReadingStateEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStorySceneEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/interactiveStories/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/interactiveStories/tags/ReadStatusTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/interactiveStories/tags/RootSceneTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/interactiveStories/tags/StoryOptionTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/limits/LimitProcessor.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/limits/Limits.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/medical/FhirResourceEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/nip95/data/FileStorageEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/nip95/data/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/nip95/header/FileStorageHeaderEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/nip95/header/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/nns/NNSEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/nns/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/nns/tags/IPv4Tag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/nns/tags/IPv6Tag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/nns/tags/VersionTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/profileGallery/GalleryListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/profileGallery/ProfileGalleryEntryEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/profileGallery/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/publicMessages/PublicMessageEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/publicMessages/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/publicMessages/tags/ReceiverTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/relationshipStatus/RelationshipStatusEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/relationshipStatus/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/PetNameTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/RankTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/SummaryTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/zapPolls/PollNoteEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/zapPolls/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/zapPolls/tags/ClosedAtTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/zapPolls/tags/ConsensusThresholdTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/zapPolls/tags/MaximumTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/zapPolls/tags/MinimumTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/experimental/zapPolls/tags/PollOptionTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/lightning/LnInvoiceUtil.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/lightning/LnWithdrawalUtil.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/lightning/Lud06.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/core/AddressableEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/core/BaseAddressableEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/core/BaseReplaceableEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/core/Event.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/core/HexKey.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/core/IEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/core/Kind.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/core/Tag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/core/TagArray.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/core/TagArrayBuilder.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/crypto/DeterministicSigner.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/crypto/EventAssembler.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/crypto/EventHasher.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/crypto/KeyPair.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/crypto/Nip01.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/hints/EventHintBundle.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/hints/HintIndexer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/hints/HintProviders.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/hints/bloom/BitSetExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/hints/bloom/BloomFilterMurMur3.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/hints/bloom/MurmurHash3.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/hints/types/AddressHint.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/hints/types/EventIdHint.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/hints/types/Hint.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/hints/types/PubKeyHint.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/jackson/EventDeserializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/jackson/EventManualDeserializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/jackson/EventManualSerializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/jackson/EventSerializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/jackson/InliningTagArrayPrettyPrinter.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/jackson/JacksonExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/jackson/JsonMapper.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/jackson/TagArrayDeserializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/jackson/TagArrayManualDeserializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/jackson/TagArraySerializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/metadata/MetadataEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/metadata/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/metadata/UserMetadata.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/metadata/tags/AboutTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/metadata/tags/BannerTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/metadata/tags/DisplayNameTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/metadata/tags/Lud06Tag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/metadata/tags/Lud16Tag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/metadata/tags/NameTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/metadata/tags/Nip05Tag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/metadata/tags/PictureTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/metadata/tags/PronounsTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/metadata/tags/WebsiteTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/NostrClient.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/NostrClientSubscription.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/EventCollector.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/NostrClientSendAndWaitExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/NostrClientSingleDownloadExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayAuthenticator.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayInsertConfirmationCollector.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayLogger.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayNotifier.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/listeners/IRelayClientListener.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/listeners/RedirectRelayClientListener.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/pool/PoolEventOutbox.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/pool/PoolEventOutboxRepository.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/pool/PoolSubscriptionRepository.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/pool/RelayBasedFilter.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/pool/RelayPool.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/single/IRelayClient.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/single/Subscription.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/single/basic/BasicRelayClient.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/single/simple/OutboxCache.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/single/simple/SimpleRelayClient.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/stats/RelayStat.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/stats/RelayStats.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/subscriptions/Subscription.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/subscriptions/SubscriptionController.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/client/subscriptions/SubscriptionStats.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/AuthMessage.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/ClosedMessage.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/EoseMessage.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/EventMessage.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/Message.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/NoticeMessage.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/NotifyMessage.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/OkMessage.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/ToClientParser.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/AuthCmd.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/CloseCmd.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/Command.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/CountCmd.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/EventCmd.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/ReqCmd.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/ToRelayParser.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/filters/Filter.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/filters/FilterDeserializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/filters/FilterMatcher.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/filters/FilterSerializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/normalizer/NormalizedRelayUrl.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/normalizer/RelayUrlNormalizer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebSocket.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebSocketListener.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebsocketBuilder.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebsocketBuilderFactory.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/relay/sockets/okhttp/BasicOkHttpWebSocket.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/signers/EventTemplate.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateDeserializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateManualDeserializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/signers/NostrSigner.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/signers/NostrSignerInternal.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/signers/NostrSignerSync.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/signers/SignerExceptions.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/signers/caches/CacheResults.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/signers/caches/DecryptCache.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/store/README.md (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/AddressableModule.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/DeletionRequestModule.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/EphemeralModule.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/EventIndexesModule.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/EventStore.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/ExpirationModule.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/FullTextSearchModule.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/ReplaceableModule.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/RightToVanishModule.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/SQLiteEventStore.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/StatementCache.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/sql/Condition.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/sql/SqlSelectionBuilder.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/store/sqlite/sql/WhereClauseBuilder.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/addressables/ATag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/addressables/Address.kt (77%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/addressables/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/addressables/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/addressables/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/dTags/DTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/dTags/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/dTags/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/dTags/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/events/ETag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/events/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/events/EventReference.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/events/GenericETag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/events/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/events/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/geohash/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/geohash/GeoHashTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/geohash/GeohashPrecision.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/geohash/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/geohash/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/hashtags/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/hashtags/HashtagTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/hashtags/MipMapHashTags.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/hashtags/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/hashtags/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/kinds/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/kinds/KindTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/kinds/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/kinds/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/people/EntityExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/people/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/people/PTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/people/PubKeyReferenceTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/people/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/people/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/publishedAt/PublishedAtProvider.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/references/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/references/ReferenceTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/references/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip01Core/tags/references/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip02FollowList/ContactListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip02FollowList/ImmutableListOfLists.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip02FollowList/RelaySet.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip02FollowList/tags/ContactTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip03Timestamp/OtsEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip03Timestamp/OtsResolver.kt (90%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip03Timestamp/OtsResolverBuilder.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip03Timestamp/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip03Timestamp/VerificationState.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip03Timestamp/VerificationStateCache.kt (100%) create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/BitcoinExplorer.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/BlockHeader.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarBuilder.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/DetachedTimestampFile.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/Hash.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendar.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendarAsyncSubmit.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/Merkle.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/OpenTimestamps.kt rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip03Timestamp/ots/README.md (100%) create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamDeserializationContext.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamSerializationContext.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/Timestamp.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/Utils.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/VerifyResult.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/BitcoinBlockHeaderAttestation.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/PendingAttestation.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/TimeAttestation.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/UnknownAttestation.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Digest.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/ExtendedDigest.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/GeneralDigest.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/KeccakDigest.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Memoable.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Pack.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/RIPEMD160Digest.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/CommitmentNotFoundException.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/DeserializationException.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/ExceededSizeException.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/UrlException.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/VerificationException.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/BlockstreamExplorer.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Calendar.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/CalendarAsyncSubmit.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/CalendarPureJavaBuilder.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Request.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Response.kt rename {amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots => quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp}/OkHttpBitcoinExplorer.kt (92%) rename {amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots => quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp}/OkHttpCalendar.kt (92%) rename {amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots => quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp}/OkHttpCalendarAsyncSubmit.kt (96%) rename {amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots => quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp}/OkHttpCalendarBuilder.kt (96%) rename {amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots => quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp}/OkHttpOtsResolverBuilder.kt (71%) rename {amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots => quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp}/OtsBlockHeightCache.kt (95%) create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/Op.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpAppend.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpBinary.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpCrypto.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpKECCAK256.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpPrepend.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpRIPEMD160.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA1.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA256.kt create mode 100644 quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpUnary.kt rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip03Timestamp/tags/TargetEventKindTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip03Timestamp/tags/TargetEventTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip04Dm/PrivateDMCache.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip04Dm/crypto/AESCBC.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip04Dm/crypto/EncryptedInfo.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip04Dm/crypto/Encryption.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip04Dm/crypto/Nip04.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip04Dm/messages/PrivateDmEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip04Dm/messages/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip05DnsIdentifiers/Nip05.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip06KeyDerivation/Bip32SeedDerivation.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39KeyPath.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39Mnemonics.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip06KeyDerivation/Nip06.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip09Deletions/DeletionEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip09Deletions/DeletionIndex.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip10Notes/BaseNoteEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip10Notes/BaseThreadedEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip10Notes/TextNoteEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip10Notes/content/ContentHashTags.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip10Notes/content/IndexedTags.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip10Notes/content/NostrUris.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip10Notes/content/Urls.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip10Notes/tags/MarkedETag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip10Notes/tags/Positional.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip10Notes/tags/ReplyBuilder.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip10Notes/tags/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip11RelayInfo/Nip11RelayInformation.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip13Pow/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip13Pow/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip13Pow/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip13Pow/miner/ByteArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip13Pow/miner/MiningBuffer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip13Pow/miner/PoWMiner.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip13Pow/miner/PoWRankEvaluator.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip13Pow/tags/PoWTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip14Subject/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip14Subject/SubjectTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip14Subject/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip14Subject/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/NIP17Factory.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/base/BaseDMGroupEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/base/ChatroomKey.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/base/ChatroomKeyable.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/base/NIP17Group.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/files/ChatMessageEncryptedFileHeaderEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/files/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/files/encryption/AESGCM.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/files/encryption/NostrCipher.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionAlgo.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionKey.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionNonce.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/files/tags/FileTypeTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/messages/ChatMessageEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/messages/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/settings/ChatMessageRelayListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip17Dm/settings/tags/RelayTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip18Reposts/GenericRepostEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip18Reposts/RepostEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip18Reposts/quotes/EntityExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip18Reposts/quotes/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip18Reposts/quotes/QAddressableTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip18Reposts/quotes/QEventTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip18Reposts/quotes/QTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/ATagExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/ByteArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/ListEntityExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/Nip19Parser.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/TlvBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/TlvTypes.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/bech32/Bech32Util.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/entities/Entity.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/entities/NAddress.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/entities/NEmbed.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/entities/NEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/entities/NNote.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/entities/NProfile.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/entities/NPub.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/entities/NRelay.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/entities/NSec.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/tlv/Tlv.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip19Bech32/tlv/TlvBuilder.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip21UriScheme/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip22Comments/CommentEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip22Comments/RootScope.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip22Comments/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAddressTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAuthorTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip22Comments/tags/ReplyEventTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip22Comments/tags/ReplyIdentifierTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip22Comments/tags/ReplyKindTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip22Comments/tags/RootAddressTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip22Comments/tags/RootAuthorTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip22Comments/tags/RootEventTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip22Comments/tags/RootIdentifierTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip22Comments/tags/RootKindTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip23LongContent/LongTextNoteEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip23LongContent/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip23LongContent/tags/ImageTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip23LongContent/tags/PublishedAtTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip23LongContent/tags/SummaryTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip23LongContent/tags/TitleTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip25Reactions/ReactionEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelCreateEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelHideMessageEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMetadataEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMuteUserEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip28PublicChat/base/BasePublicChatEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip28PublicChat/base/ChannelData.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip28PublicChat/base/IsInPublicChatChannel.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip28PublicChat/base/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip28PublicChat/list/ChannelListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip28PublicChat/list/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip28PublicChat/list/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip28PublicChat/list/tags/ChannelTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip28PublicChat/message/ChannelMessageEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip30CustomEmoji/CustomEmoji.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip30CustomEmoji/EmojiUrlTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip30CustomEmoji/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip30CustomEmoji/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip30CustomEmoji/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip30CustomEmoji/pack/EmojiPackEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip30CustomEmoji/selection/EmojiPackSelectionEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip30CustomEmoji/selection/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip31Alts/AltTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip31Alts/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip31Alts/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip31Alts/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip34Git/issue/GitIssueEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip34Git/issue/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip34Git/patch/GitPatchEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip34Git/reply/GitReplyEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip34Git/reply/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip34Git/repository/GitRepositoryEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip34Git/repository/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip34Git/repository/tags/CloneTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip34Git/repository/tags/DescriptionTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip34Git/repository/tags/NameTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip34Git/repository/tags/WebTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip35Torrents/DefaultTrackers.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip35Torrents/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip35Torrents/TorrentCommentEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip35Torrents/TorrentEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip35Torrents/tags/BtihTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip35Torrents/tags/FileTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip35Torrents/tags/InfoHashTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip35Torrents/tags/TrackerTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip36SensitiveContent/ContentWarningTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip36SensitiveContent/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip36SensitiveContent/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip36SensitiveContent/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip37Drafts/DraftWrapCache.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip37Drafts/DraftWrapEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip37Drafts/ExposeInDraft.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip37Drafts/privateOutbox/PrivateOutboxRelayListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip38UserStatus/StatusEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip39ExtIdentities/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip39ExtIdentities/GitHubIdentity.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip39ExtIdentities/IdentityClaimTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip39ExtIdentities/MastodonIdentity.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip39ExtIdentities/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip39ExtIdentities/TelegramIdentity.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip39ExtIdentities/TwitterIdentity.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip39ExtIdentities/UnsupportedIdentity.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip40Expiration/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip40Expiration/ExpirationTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip40Expiration/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip40Expiration/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip42RelayAuth/RelayAuthEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip42RelayAuth/tags/ChallengeTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip42RelayAuth/tags/RelayTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip44Encryption/EncryptedInfoString.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip44Encryption/Nip44.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip44Encryption/Nip44v1.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip44Encryption/Nip44v2.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip44Encryption/SharedKeyCache.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip44Encryption/crypto/Hkdf.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerMessage.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequest.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestConnect.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestGetPublicKey.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestGetRelays.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip04Decrypt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip04Encrypt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip44Decrypt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip44Encrypt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestPing.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestSign.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponse.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseAck.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseDecrypt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseEncrypt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseError.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseGetRelays.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponsePong.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponsePublicKey.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip46RemoteSigner/NostrConnectEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip47WalletConnect/LnZapPaymentRequestEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip47WalletConnect/LnZapPaymentResponseEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip47WalletConnect/Nip47WalletConnect.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip47WalletConnect/NostrWalletConnectRequestCache.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip47WalletConnect/NostrWalletConnectResponseCache.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip47WalletConnect/Request.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip47WalletConnect/RequestDeserializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip47WalletConnect/Response.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip47WalletConnect/ResponseDeserializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip48ProxyTags/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip48ProxyTags/ProxyTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip48ProxyTags/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip48ProxyTags/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip49PrivKeyEnc/ByteArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip49PrivKeyEnc/Nip49.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip49PrivKeyEnc/PBKDF.java (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip49PrivKeyEnc/SCrypt.java (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip49PrivKeyEnc/SecretKeyOrEmptySpec.java (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip50Search/SearchRelayListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip50Search/SearchableEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/PinListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/PrivateTagArrayBuilder.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/PrivateTagArrayEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/PrivateTagArrayEventCache.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/bookmarkList/BookmarkListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/bookmarkList/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/bookmarkList/tags/AddressBookmark.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/bookmarkList/tags/BookmarkIdTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/bookmarkList/tags/EventBookmark.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/encryption/NostrSignerExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/encryption/PrivateTagsInContent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/followList/FollowListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/followList/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/followList/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/geohashList/GeohashListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/geohashList/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/geohashList/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/hashtagList/HashtagListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/hashtagList/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/hashtagList/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/muteList/MuteListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/muteList/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/muteList/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/muteList/tags/MuteTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/muteList/tags/UserTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/muteList/tags/WordTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/peopleList/PeopleListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/peopleList/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/peopleList/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/relayLists/BlockedRelayListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/relayLists/BroadcastRelayListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/relayLists/IndexerRelayListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/relayLists/ProxyRelayListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/relayLists/TrustedRelayListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/relayLists/tags/RelayTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/relayLists/tags/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/relayLists/tags/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/relaySets/RelaySetEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/tags/DescriptionTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/tags/ImageTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/tags/NameTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/tags/RelayTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip51Lists/tags/TitleTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip52Calendar/CalendarDateSlotEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip52Calendar/CalendarEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip52Calendar/CalendarRSVPEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip52Calendar/CalendarTimeSlotEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip53LiveActivities/chat/LiveActivitiesChatMessageEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip53LiveActivities/chat/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip53LiveActivities/streaming/LiveActivitiesEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/CurrentParticipantsTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/EndsTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/ParticipantTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/RelayListTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StartsTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StatusTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StreamingTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/TotalParticipantsTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip54Wiki/WikiNoteEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/SignString.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/CommandType.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/SignerResult.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/DecryptZapQuery.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/DeriveKeyQuery.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/LoginQuery.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip04DecryptQuery.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip04EncryptQuery.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip44DecryptQuery.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip44EncryptQuery.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/SignQuery.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/utils/ContentResolverExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/utils/CursorExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/IntentRequestManager.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/DecryptZapRequest.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/DeriveKeyRequest.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/LoginRequest.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip04DecryptRequest.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip04EncryptRequest.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip44DecryptRequest.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip44EncryptRequest.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/SignRequest.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/DecryptZapResponse.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/DeriveKeyResponse.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/LoginResponse.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip04DecryptResponse.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip04EncryptResponse.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip44DecryptResponse.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip44EncryptResponse.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/SignResponse.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/results/IntentResult.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/results/IntentResultJsonDeserializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/results/IntentResultJsonSerializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/permission/Permission.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/permission/PermissionDeserializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/api/permission/PermissionSerializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/client/ExternalSignerLogin.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/client/IActivityLauncher.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/client/IsExternalSignerInstalled.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/client/NostrSignerExternal.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/client/handlers/BackgroundRequestHandler.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip55AndroidSigner/client/handlers/ForegroundRequestHandler.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip56Reports/ReportEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip56Reports/ReportType.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip56Reports/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip56Reports/tags/BaseReportTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip56Reports/tags/DefaultReportTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip56Reports/tags/HashSha256Tag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip56Reports/tags/ReportedAddressTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip56Reports/tags/ReportedAuthorTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip56Reports/tags/ReportedEventTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip56Reports/tags/ServerTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/LnZapEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/LnZapEventInterface.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/LnZapPrivateEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/PrivateZapCache.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/PrivateZapEncryption.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/PrivateZapRequestBuilder.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/splits/BaseZapSplitSetup.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/splits/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/splits/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/splits/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetup.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetupLnAddress.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetupParser.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetupSerializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/zapraiser/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/zapraiser/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/zapraiser/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip57Zaps/zapraiser/ZapRaiserTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip58Badges/BadgeAwardEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip58Badges/BadgeDefinitionEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip58Badges/BadgeProfilesEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip59Giftwrap/HostStub.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip59Giftwrap/WrappedEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip59Giftwrap/rumors/Rumor.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip59Giftwrap/rumors/RumorAssembler.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip59Giftwrap/rumors/RumorDeserializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip59Giftwrap/rumors/RumorSerializer.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip59Giftwrap/seals/SealedRumorEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip59Giftwrap/wraps/GiftWrapEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip62RequestToVanish/RequestToVanishEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip62RequestToVanish/tags/RelayTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip62RequestToVanish/tags/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip62RequestToVanish/tags/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip65RelayList/AdvertisedRelayListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip65RelayList/RelayListRecommendationProcessor.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip65RelayList/tags/AdvertisedRelayInfoTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip68Picture/IMetaTagBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip68Picture/IMetaTagExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip68Picture/PictureEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip68Picture/PictureMeta.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip68Picture/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip68Picture/tags/LocationTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip68Picture/tags/UserAnnotationTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip70ProtectedEvts/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip70ProtectedEvts/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip70ProtectedEvts/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip70ProtectedEvts/tags/ProtectedTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip71Video/IMetaTagBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip71Video/IMetaTagExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip71Video/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip71Video/VideoEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip71Video/VideoHorizontalEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip71Video/VideoMeta.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip71Video/VideoNormalEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip71Video/VideoShortEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip71Video/VideoVerticalEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip71Video/tags/DurationTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip71Video/tags/SegmentTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip71Video/tags/TextTrackTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/approval/CommunityPostApprovalEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/approval/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/approval/tags/ApprovedAddressTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/approval/tags/ApprovedEventTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/definition/CommunityDefinitionEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/definition/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/DescriptionTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ImageTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ModeratorTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/NameTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RelayTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RulesTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/follow/CommunityListEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/follow/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/follow/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip72ModCommunities/follow/tags/CommunityTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/CommentEventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/ExternalId.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/books/BookId.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/books/CommentEventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/location/CommentEventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/location/GeohashId.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/movies/CommentEventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/movies/MovieId.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/papers/CommentEventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/papers/PaperId.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/CommentEventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/PodcastEpisodeId.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/PodcastFeedId.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/PodcastPublisherId.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/topics/CommentEventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/topics/HashtagId.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/urls/CommentEventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip73ExternalIds/urls/UrlId.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip75ZapGoals/GoalEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip75ZapGoals/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip75ZapGoals/tags/AmountTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip75ZapGoals/tags/ClosedAtTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip75ZapGoals/tags/RelayListTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip78AppData/AppSpecificDataEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip84Highlights/HighlightEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip84Highlights/tags/CommentTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip84Highlights/tags/ContextTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip89AppHandlers/PlatformType.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/ClientTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip89AppHandlers/definition/AppDefinitionEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip89AppHandlers/definition/AppMetadata.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip89AppHandlers/definition/EntityType.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip89AppHandlers/definition/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip89AppHandlers/definition/tags/PlatformLinkTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/AppRecommendationEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/tags/RecommendationTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip90Dvms/NIP90ContentDiscoveryRequestEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip90Dvms/NIP90ContentDiscoveryResponseEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip90Dvms/NIP90StatusEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip90Dvms/NIP90UserDiscoveryRequestEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip90Dvms/NIP90UserDiscoveryResponseEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip92IMeta/EventExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip92IMeta/IMetaTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip92IMeta/IMetaTagBuilder.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip92IMeta/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip92IMeta/TagArrayExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/FileHeaderEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/IMetaTagBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/tags/BlurhashTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/tags/DimensionTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/tags/FallbackTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/tags/HashSha256Tag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/tags/ImageTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/tags/MagnetTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/tags/MimeTypeTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/tags/OriginalHashTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/tags/ServiceTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/tags/SizeTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/tags/SummaryTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/tags/ThumbTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/tags/TorrentInfoHash.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip94FileMetadata/tags/UrlTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip96FileStorage/HttpUrlFormatter.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip96FileStorage/actions/DeleteResult.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip96FileStorage/actions/UploadResult.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip96FileStorage/config/FileServersEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip96FileStorage/config/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip96FileStorage/config/tags/ServerTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip96FileStorage/info/ServerInfo.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip96FileStorage/info/ServerInfoParser.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip98HttpAuth/HTTPAuthorizationEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip98HttpAuth/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip98HttpAuth/tags/MethodTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip98HttpAuth/tags/PayloadHashTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip98HttpAuth/tags/UrlTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip99Classifieds/ClassifiedsEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip99Classifieds/ProductImageMeta.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip99Classifieds/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip99Classifieds/tags/ConditionTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip99Classifieds/tags/LocationTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip99Classifieds/tags/PriceTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nip99Classifieds/tags/StatusTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipA0VoiceMessages/AudioMeta.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipA0VoiceMessages/BaseVoiceEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipA0VoiceMessages/IMetaTagBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipA0VoiceMessages/IMetaTagExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipA0VoiceMessages/TagArrayBuilderExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipA0VoiceMessages/VoiceEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipA0VoiceMessages/VoiceReplyEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/DurationTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/HashSha256Tag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/MimeTypeTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/ReplyAuthorTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/ReplyEventTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/ReplyKindTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/WaveformTag.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipB7Blossom/BlossomAuthorizationEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/nipB7Blossom/BlossomServersEvent.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/ArrayUtils.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/CacheCollectors.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/CacheOperations.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/Ensure.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/GZip.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/Hex.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/Hmac512.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/IterableExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/LargeCache.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/LargeSoftCache.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/LibSodiumInstance.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/MapOfSetBuilder.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/ParallelUtils.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/RandomInstance.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/Secp256k1Instance.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/StringUtils.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/TimeUtils.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/UriReferenceExt.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/sha256/Sha256.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/sha256/Sha256Hasher.kt (100%) rename quartz/src/{main/java => androidMain/kotlin}/com/vitorpamplona/quartz/utils/sha256/Sha256Pool.kt (100%) create mode 100644 quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/Platform.kt create mode 100644 quartz/src/iosMain/kotlin/com/vitorpamplona/quartz/Platform.ios.kt delete mode 100644 quartz/src/main/AndroidManifest.xml delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/BitcoinExplorer.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/BlockHeader.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/BlockstreamExplorer.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Calendar.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarAsyncSubmit.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarBuilder.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarPureJavaBuilder.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/DetachedTimestampFile.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Hash.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendar.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendarAsyncSubmit.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Merkle.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/OpenTimestamps.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamDeserializationContext.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamSerializationContext.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Timestamp.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Utils.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/VerifyResult.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/BitcoinBlockHeaderAttestation.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/EthereumBlockHeaderAttestation.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/LitecoinBlockHeaderAttestation.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/PendingAttestation.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/TimeAttestation.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/UnknownAttestation.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Digest.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/ExtendedDigest.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/GeneralDigest.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/KeccakDigest.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Memoable.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Pack.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/RIPEMD160Digest.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/CommitmentNotFoundException.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/DeserializationException.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/ExceededSizeException.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/UrlException.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/VerificationException.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Request.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Response.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/Op.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpAppend.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpBinary.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpCrypto.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpKECCAK256.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpPrepend.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpRIPEMD160.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA1.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA256.java delete mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpUnary.java delete mode 100644 quartz/src/test/java/android/util/Log.java diff --git a/.gitignore b/.gitignore index f527be142..b4ec9c645 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ /.idea/other.xml /.idea/runConfigurations.xml /.idea/ChatHistory_schema_v2.xml +/.idea/artifacts/* .DS_Store /build /captures diff --git a/README.md b/README.md index f32278427..d1bf11d23 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -
+
Amethyst Logo diff --git a/amethyst/src/androidTest/java/com/vitorpamplona/amethyst/OkHttpOtsTest.kt b/amethyst/src/androidTest/java/com/vitorpamplona/amethyst/OkHttpOtsTest.kt index d03991147..91f63f94d 100644 --- a/amethyst/src/androidTest/java/com/vitorpamplona/amethyst/OkHttpOtsTest.kt +++ b/amethyst/src/androidTest/java/com/vitorpamplona/amethyst/OkHttpOtsTest.kt @@ -21,14 +21,14 @@ package com.vitorpamplona.amethyst import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.vitorpamplona.amethyst.service.ots.OkHttpBitcoinExplorer -import com.vitorpamplona.amethyst.service.ots.OkHttpCalendarBuilder -import com.vitorpamplona.amethyst.service.ots.OtsBlockHeightCache import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair import com.vitorpamplona.quartz.nip01Core.jackson.JsonMapper import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent import com.vitorpamplona.quartz.nip03Timestamp.OtsResolver +import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OkHttpBitcoinExplorer +import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OkHttpCalendarBuilder +import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OtsBlockHeightCache import junit.framework.TestCase.assertEquals import kotlinx.coroutines.runBlocking import okhttp3.OkHttpClient diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/Amethyst.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/Amethyst.kt index 70e36a3f5..b0e7de2fc 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/Amethyst.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/Amethyst.kt @@ -38,7 +38,6 @@ import com.vitorpamplona.amethyst.service.okhttp.DualHttpClientManager import com.vitorpamplona.amethyst.service.okhttp.EncryptionKeyCache import com.vitorpamplona.amethyst.service.okhttp.OkHttpWebSocket import com.vitorpamplona.amethyst.service.okhttp.ProxySettingsAnchor -import com.vitorpamplona.amethyst.service.ots.OtsBlockHeightCache import com.vitorpamplona.amethyst.service.playback.diskCache.VideoCache import com.vitorpamplona.amethyst.service.playback.diskCache.VideoCacheFactory import com.vitorpamplona.amethyst.service.relayClient.CacheClientConnector @@ -51,6 +50,7 @@ import com.vitorpamplona.amethyst.service.uploads.nip95.Nip95CacheFactory import com.vitorpamplona.amethyst.ui.tor.TorManager import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient import com.vitorpamplona.quartz.nip03Timestamp.VerificationStateCache +import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OtsBlockHeightCache import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index f2318aa1d..33b3b8532 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -89,7 +89,6 @@ import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavFilter import com.vitorpamplona.amethyst.model.topNavFeeds.OutboxLoaderState import com.vitorpamplona.amethyst.model.torState.TorRelayState import com.vitorpamplona.amethyst.service.location.LocationState -import com.vitorpamplona.amethyst.service.ots.OkHttpOtsResolverBuilder import com.vitorpamplona.amethyst.service.uploads.FileHeader import com.vitorpamplona.quartz.experimental.bounties.BountyAddValueEvent import com.vitorpamplona.quartz.experimental.edits.TextNoteModificationEvent @@ -136,6 +135,7 @@ import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags import com.vitorpamplona.quartz.nip01Core.tags.people.hasAnyTaggedUser import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUserIds import com.vitorpamplona.quartz.nip01Core.tags.references.references +import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OkHttpOtsResolverBuilder import com.vitorpamplona.quartz.nip04Dm.PrivateDMCache import com.vitorpamplona.quartz.nip04Dm.messages.PrivateDmEvent import com.vitorpamplona.quartz.nip09Deletions.DeletionEvent @@ -323,7 +323,9 @@ class Account( val otsResolverBuilder: OkHttpOtsResolverBuilder = OkHttpOtsResolverBuilder( - Amethyst.instance.okHttpClients, + { + Amethyst.instance.okHttpClients.getHttpClient(privacyState.shouldUseTorForMoneyOperations(it)) + }, privacyState::shouldUseTorForMoneyOperations, Amethyst.instance.otsBlockHeightCache, ) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip03Timestamp/OtsState.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip03Timestamp/OtsState.kt index 44f316caa..763d72419 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip03Timestamp/OtsState.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip03Timestamp/OtsState.kt @@ -24,10 +24,10 @@ import android.util.Log import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.Note -import com.vitorpamplona.amethyst.service.ots.OkHttpOtsResolverBuilder import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent +import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OkHttpOtsResolverBuilder import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.update import java.util.Base64 diff --git a/ammolite/build.gradle b/ammolite/build.gradle index 9c8f5dc4e..3578fb626 100644 --- a/ammolite/build.gradle +++ b/ammolite/build.gradle @@ -54,10 +54,10 @@ dependencies { implementation libs.androidx.core.ktx // Compose's @Immutable and @Stable classes - implementation libs.androidx.runtime.runtime - + implementation libs.androidx.compose.runtime implementation project(path: ':quartz') + testImplementation libs.junit androidTestImplementation libs.androidx.junit diff --git a/build.gradle b/build.gradle index 7f204f9e8..4acc357f8 100644 --- a/build.gradle +++ b/build.gradle @@ -7,6 +7,8 @@ plugins { alias(libs.plugins.diffplugSpotless) alias(libs.plugins.googleServices) apply false alias(libs.plugins.jetbrainsComposeCompiler) apply false + alias(libs.plugins.kotlinMultiplatform) apply false + alias(libs.plugins.androidKotlinMultiplatformLibrary) apply false } allprojects { @@ -39,9 +41,18 @@ allprojects { subprojects { afterEvaluate { - tasks.named("preBuild") { - dependsOn("spotlessApply") + try { + tasks.named("preBuild") { + dependsOn("spotlessApply") + } + } catch (UnknownTaskException ignored) { + tasks.matching { + it.name.startsWith("pre") && it.name.endsWith("Build") + }.configureEach { + dependsOn("spotlessApply") + } } + } } diff --git a/commons/build.gradle b/commons/build.gradle index cba6f3a55..b37d1acc4 100644 --- a/commons/build.gradle +++ b/commons/build.gradle @@ -51,7 +51,6 @@ composeCompiler { dependencies { implementation project(path: ':quartz') - // Import @Immutable and @Stable implementation platform(libs.androidx.compose.bom) implementation libs.androidx.ui diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f44afee03..dbd7474fe 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -54,6 +54,9 @@ zxing = "3.5.3" zxingAndroidEmbedded = "4.3.0" windowCoreAndroid = "1.4.0" androidxCamera = "1.4.2" +kotlinStdlib = "2.2.10" +kotlinTest = "2.2.10" +core = "1.7.0" [libraries] abedElazizShe-image-compressor = { group = "com.github.AbedElazizShe", name = "LightCompressor", version.ref = "lightcompressor" } @@ -69,11 +72,12 @@ androidx-camera-extensions = { module = "androidx.camera:camera-extensions", ver androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "androidxCamera" } androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "androidxCamera" } androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } +androidx-compose-foundation = { group = "androidx.compose.foundation", name = "foundation" } +androidx-compose-runtime = { group = "androidx.compose.runtime", name = "runtime" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastore" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } androidx-fragment-ktx = { group = "androidx.fragment", name = "fragment-ktx", version.ref = "fragmentKtx" } -androidx-compose-foundation = { group = "androidx.compose.foundation", name = "foundation" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidxJunit" } androidx-junit-ktx = { group = "androidx.test.ext", name = "junit-ktx", version.ref = "androidxJunit" } androidx-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycleRuntimeKtx" } @@ -89,7 +93,6 @@ androidx-media3-session = { group = "androidx.media3", name = "media3-session", androidx-media3-ui = { group = "androidx.media3", name = "media3-ui", version.ref = "media3" } androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" } androidx-runner = { group = "androidx.test", name = "runner", version.ref = "runner" } -androidx-runtime-runtime = { group = "androidx.compose.runtime", name = "runtime" } androidx-security-crypto-ktx = { group = "androidx.security", name = "security-crypto-ktx", version.ref = "securityCryptoKtx" } androidx-ui = { group = "androidx.compose.ui", name = "ui" } androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } @@ -121,8 +124,12 @@ kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-cor okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" } okhttpCoroutines = { group = "com.squareup.okhttp3", name = "okhttp-coroutines", version.ref = "okhttp" } rfc3986-normalizer = { group = "org.czeal", name = "rfc3986", version.ref = "rfc3986" } +secp256k1-kmp-common = { group = "fr.acinq.secp256k1", name = "secp256k1-kmp", version.ref = "secp256k1KmpJniAndroid" } secp256k1-kmp-jni-android = { group = "fr.acinq.secp256k1", name = "secp256k1-kmp-jni-android", version.ref = "secp256k1KmpJniAndroid" } secp256k1-kmp-jni-jvm = { group = "fr.acinq.secp256k1", name = "secp256k1-kmp-jni-jvm", version.ref = "secp256k1KmpJniAndroid" } +secp256k1-kmp-jni-jvm-linux = { group = "fr.acinq.secp256k1", name = "secp256k1-kmp-jni-jvm-linux", version.ref = "secp256k1KmpJniAndroid" } +secp256k1-kmp-jni-jvm-darwin = { group = "fr.acinq.secp256k1", name = "secp256k1-kmp-jni-jvm-darwin", version.ref = "secp256k1KmpJniAndroid" } +secp256k1-kmp-jni-jvm-mingw = { group = "fr.acinq.secp256k1", name = "secp256k1-kmp-jni-jvm-mingw", version.ref = "secp256k1KmpJniAndroid" } tor-android = { module = "info.guardianproject:tor-android", version.ref = "torAndroid" } unifiedpush = { group = "com.github.UnifiedPush", name = "android-connector", version.ref = "unifiedpush" } url-detector = { group = "io.github.url-detector", name = "url-detector", version.ref = "urlDetector" } @@ -135,6 +142,9 @@ zoomable = { group = "net.engawapg.lib", name = "zoomable", version.ref = "zooma zxing = { group = "com.google.zxing", name = "core", version.ref = "zxing" } zxing-embedded = { group = "com.journeyapps", name = "zxing-android-embedded", version.ref = "zxingAndroidEmbedded" } androidx-window-core-android = { group = "androidx.window", name = "window-core-android", version.ref = "windowCoreAndroid" } +kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlinStdlib" } +kotlin-test = { group = "org.jetbrains.kotlin", name = "kotlin-test", version.ref = "kotlinTest" } +androidx-core = { group = "androidx.test", name = "core", version.ref = "core" } [plugins] androidApplication = { id = "com.android.application", version.ref = "agp" } @@ -146,4 +156,6 @@ jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "k jetbrainsKotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } jetbrainsComposeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } serialization = { id = 'org.jetbrains.kotlin.plugin.serialization', version.ref = 'kotlinxSerializationPlugin' } -parcelize = { id = "kotlin-parcelize" } \ No newline at end of file +parcelize = { id = "kotlin-parcelize" } +kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } +androidKotlinMultiplatformLibrary = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" } \ No newline at end of file diff --git a/quartz/build.gradle b/quartz/build.gradle deleted file mode 100644 index f4e91c4d0..000000000 --- a/quartz/build.gradle +++ /dev/null @@ -1,88 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -plugins { - alias(libs.plugins.androidLibrary) - alias(libs.plugins.jetbrainsKotlinAndroid) - alias(libs.plugins.parcelize) -} - -android { - namespace = 'com.vitorpamplona.quartz' - compileSdk = libs.versions.android.compileSdk.get().toInteger() - - defaultConfig { - minSdk = libs.versions.android.minSdk.get().toInteger() - targetSdk = libs.versions.android.targetSdk.get().toInteger() - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles "consumer-rules.pro" - } - - buildTypes { - release { - minifyEnabled = true - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - create("benchmark") { - initWith(getByName("release")) - signingConfig = signingConfigs.debug - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_21 - targetCompatibility JavaVersion.VERSION_21 - } - packagingOptions { - resources { - excludes += ['**/libscrypt.dylib'] - } - } -} - -kotlin { - compilerOptions { - jvmTarget = JvmTarget.JVM_21 - freeCompilerArgs.add("-Xstring-concat=inline") - } -} - -dependencies { - implementation libs.androidx.core.ktx - implementation platform(libs.androidx.compose.bom) - - // @Immutable and @Stable - implementation libs.androidx.runtime.runtime - - // Bitcoin secp256k1 bindings to Android - api libs.secp256k1.kmp.jni.android - - // LibSodium for ChaCha encryption (NIP-44) - // Wait for @aar support in version catalogs - - // implementation 'com.goterl:lazysodium-android:5.2.0@aar' - // implementation 'net.java.dev.jna:jna:5.17.0@aar' - - implementation variantOf(libs.lazysodium.android) { artifactType("aar") } - implementation variantOf(libs.jna) { artifactType("aar") } - - // Performant Parser of JSONs into Events - api libs.jackson.module.kotlin - - // immutable collections to avoid recomposition - api libs.kotlinx.collections.immutable - - // Parses URLs from Text: - api libs.url.detector - - // Normalizes URLs - api libs.rfc3986.normalizer - - // Websockets API - implementation libs.okhttp - - testImplementation libs.junit - testImplementation libs.secp256k1.kmp.jni.jvm - androidTestImplementation platform(libs.androidx.compose.bom) - androidTestImplementation libs.androidx.junit - androidTestImplementation libs.androidx.espresso.core -} \ No newline at end of file diff --git a/quartz/build.gradle.kts b/quartz/build.gradle.kts new file mode 100644 index 000000000..eb41b2331 --- /dev/null +++ b/quartz/build.gradle.kts @@ -0,0 +1,157 @@ +plugins { + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.androidKotlinMultiplatformLibrary) +} + +kotlin { + jvm() + + // Target declarations - add or remove as needed below. These define + // which platforms this KMP module supports. + // See: https://kotlinlang.org/docs/multiplatform-discover-project.html#targets + androidLibrary { + namespace = "com.vitorpamplona.quartz" + compileSdk = libs.versions.android.compileSdk.get().toInt() + minSdk = libs.versions.android.minSdk.get().toInt() + + withHostTestBuilder { + } + + withDeviceTestBuilder { + sourceSetTreeName = "test" + }.configure { + instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + } + + compilerOptions { + freeCompilerArgs.add("-Xstring-concat=inline") + } + + // For iOS targets, this is also where you should + // configure native binary output. For more information, see: + // https://kotlinlang.org/docs/multiplatform-build-native-binaries.html#build-xcframeworks + + // A step-by-step guide on how to include this library in an XCode + // project can be found here: + // https://developer.android.com/kotlin/multiplatform/migrate + val xcfName = "quartz-kmpKit" + + iosX64 { + binaries.framework { + baseName = xcfName + } + } + + iosArm64 { + binaries.framework { + baseName = xcfName + } + } + + iosSimulatorArm64 { + binaries.framework { + baseName = xcfName + } + } + + // Source set declarations. + // Declaring a target automatically creates a source set with the same name. By default, the + // Kotlin Gradle Plugin creates additional source sets that depend on each other, since it is + // common to share sources between related targets. + // See: https://kotlinlang.org/docs/multiplatform-hierarchy.html + sourceSets { + commonMain { + dependencies { + implementation(libs.kotlin.stdlib) + implementation(project.dependencies.platform(libs.androidx.compose.bom)) + + // @Immutable and @Stable + implementation(libs.androidx.compose.runtime) + + api(libs.secp256k1.kmp.common) + } + } + + jvmMain { + dependencies { + // Bitcoin secp256k1 bindings + api(libs.secp256k1.kmp.jni.jvm) + + // Performant Parser of JSONs into Events + api(libs.jackson.module.kotlin) + + // immutable collections to avoid recomposition + api(libs.kotlinx.collections.immutable) + + // Parses URLs from Text: + api(libs.url.detector) + + // Normalizes URLs + api(libs.rfc3986.normalizer) + + // Websockets API + implementation(libs.okhttp) + } + } + + commonTest { + dependencies { + implementation(libs.kotlin.test) + // Bitcoin secp256k1 bindings + api(libs.secp256k1.kmp.jni.jvm) + } + } + + androidMain { + dependencies { + implementation(libs.androidx.core.ktx) + + // @Immutable and @Stable + implementation(libs.androidx.compose.runtime) + + // Bitcoin secp256k1 bindings to Android + api(libs.secp256k1.kmp.jni.android) + + // LibSodium for ChaCha encryption (NIP-44) + implementation ("com.goterl:lazysodium-android:5.2.0@aar") + implementation ("net.java.dev.jna:jna:5.17.0@aar") + + // Performant Parser of JSONs into Events + api(libs.jackson.module.kotlin) + + // immutable collections to avoid recomposition + api(libs.kotlinx.collections.immutable) + + // Parses URLs from Text: + api(libs.url.detector) + + // Normalizes URLs + api(libs.rfc3986.normalizer) + + // Websockets API + implementation(libs.okhttp) + } + } + + getByName("androidDeviceTest") { + dependencies { + implementation(libs.androidx.runner) + implementation(libs.androidx.core) + implementation(libs.androidx.junit) + implementation(libs.androidx.espresso.core) + } + } + + iosMain { + dependencies { + // Add iOS-specific dependencies here. This a source set created by Kotlin Gradle + // Plugin (KGP) that each specific iOS target (e.g., iosX64) depends on as + // part of KMP’s default source set hierarchy. Note that this source set depends + // on common by default and will correctly pull the iOS artifacts of any + // KMP dependencies declared in commonMain. + } + } + } + +} \ No newline at end of file diff --git a/quartz/notebooks/Kind1Test.ipynb b/quartz/notebooks/Kind1Test.ipynb deleted file mode 100644 index 707a981a8..000000000 --- a/quartz/notebooks/Kind1Test.ipynb +++ /dev/null @@ -1,147 +0,0 @@ -{ - "cells": [ - { - "metadata": {}, - "cell_type": "markdown", - "source": "## Creating a new Kind 1 post" - }, - { - "metadata": { - "jupyter": { - "is_executing": true - } - }, - "cell_type": "code", - "source": [ - "USE {\n", - " dependencies(\"fr.acinq.secp256k1:secp256k1-kmp-jni-jvm:0.17.3\")\n", - " dependencies(\"com.goterl:lazysodium-java:5.1.4\")\n", - " dependencies(\"net.java.dev.jna:jna:5.17.0\")\n", - "\n", - " import(\"com.vitorpamplona.quartz.*\")\n", - "}" - ], - "outputs": [], - "execution_count": null - }, - { - "cell_type": "code", - "metadata": { - "collapsed": true, - "ExecuteTime": { - "end_time": "2025-06-03T14:42:40.051027Z", - "start_time": "2025-06-03T14:42:40.023052Z" - } - }, - "source": [ - "import fr.acinq.secp256k1.Secp256k1\n", - "\n", - "import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair\n", - "import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal\n", - "import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerSync\n", - "import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent\n", - "\n", - "val signer = NostrSignerSync()\n", - "val kind1Template = TextNoteEvent.build(\"New kind 1 Post\")\n", - "val signedEvent = signer.sign(kind1Template)\n", - "\n", - "println(signedEvent)" - ], - "outputs": [ - { - "ename": "org.jetbrains.kotlinx.jupyter.exceptions.ReplCompilerException", - "evalue": "at Cell In[5], line 3, column 43: Unresolved reference: crypto\nat Cell In[5], line 4, column 43: Unresolved reference: signers\nat Cell In[5], line 5, column 43: Unresolved reference: signers\nat Cell In[5], line 6, column 33: Unresolved reference: nip10Notes\nat Cell In[5], line 8, column 14: Unresolved reference: NostrSignerSync\nat Cell In[5], line 9, column 21: Unresolved reference: TextNoteEvent\nat Cell In[5], line 12, column 1: Overload resolution ambiguity: \npublic inline fun println(message: Any?): Unit defined in kotlin.io\npublic inline fun println(message: Boolean): Unit defined in kotlin.io\npublic inline fun println(message: Byte): Unit defined in kotlin.io\npublic inline fun println(message: Char): Unit defined in kotlin.io\npublic inline fun println(message: CharArray): Unit defined in kotlin.io\npublic inline fun println(message: Double): Unit defined in kotlin.io\npublic inline fun println(message: Float): Unit defined in kotlin.io\npublic inline fun println(message: Int): Unit defined in kotlin.io\npublic inline fun println(message: Long): Unit defined in kotlin.io\npublic inline fun println(message: Short): Unit defined in kotlin.io", - "output_type": "error", - "traceback": [ - "org.jetbrains.kotlinx.jupyter.exceptions.ReplCompilerException: at Cell In[5], line 3, column 43: Unresolved reference: crypto", - "at Cell In[5], line 4, column 43: Unresolved reference: signers", - "at Cell In[5], line 5, column 43: Unresolved reference: signers", - "at Cell In[5], line 6, column 33: Unresolved reference: nip10Notes", - "at Cell In[5], line 8, column 14: Unresolved reference: NostrSignerSync", - "at Cell In[5], line 9, column 21: Unresolved reference: TextNoteEvent", - "at Cell In[5], line 12, column 1: Overload resolution ambiguity: ", - "public inline fun println(message: Any?): Unit defined in kotlin.io", - "public inline fun println(message: Boolean): Unit defined in kotlin.io", - "public inline fun println(message: Byte): Unit defined in kotlin.io", - "public inline fun println(message: Char): Unit defined in kotlin.io", - "public inline fun println(message: CharArray): Unit defined in kotlin.io", - "public inline fun println(message: Double): Unit defined in kotlin.io", - "public inline fun println(message: Float): Unit defined in kotlin.io", - "public inline fun println(message: Int): Unit defined in kotlin.io", - "public inline fun println(message: Long): Unit defined in kotlin.io", - "public inline fun println(message: Short): Unit defined in kotlin.io", - "\tat org.jetbrains.kotlinx.jupyter.repl.impl.JupyterCompilerImpl.compileSync(JupyterCompilerImpl.kt:208)", - "\tat org.jetbrains.kotlinx.jupyter.repl.impl.InternalEvaluatorImpl.eval(InternalEvaluatorImpl.kt:126)", - "\tat org.jetbrains.kotlinx.jupyter.repl.impl.CellExecutorImpl$execute$1$result$1.invoke(CellExecutorImpl.kt:80)", - "\tat org.jetbrains.kotlinx.jupyter.repl.impl.CellExecutorImpl$execute$1$result$1.invoke(CellExecutorImpl.kt:78)", - "\tat org.jetbrains.kotlinx.jupyter.repl.impl.ReplForJupyterImpl.withHost(ReplForJupyterImpl.kt:791)", - "\tat org.jetbrains.kotlinx.jupyter.repl.impl.CellExecutorImpl.execute-L4Nmkdk(CellExecutorImpl.kt:78)", - "\tat org.jetbrains.kotlinx.jupyter.repl.execution.CellExecutor$DefaultImpls.execute-L4Nmkdk$default(CellExecutor.kt:13)", - "\tat org.jetbrains.kotlinx.jupyter.repl.impl.ReplForJupyterImpl.evaluateUserCode-wNURfNM(ReplForJupyterImpl.kt:613)", - "\tat org.jetbrains.kotlinx.jupyter.repl.impl.ReplForJupyterImpl.evalExImpl(ReplForJupyterImpl.kt:471)", - "\tat org.jetbrains.kotlinx.jupyter.repl.impl.ReplForJupyterImpl.access$evalExImpl(ReplForJupyterImpl.kt:143)", - "\tat org.jetbrains.kotlinx.jupyter.repl.impl.ReplForJupyterImpl$evalEx$1.invoke(ReplForJupyterImpl.kt:464)", - "\tat org.jetbrains.kotlinx.jupyter.repl.impl.ReplForJupyterImpl$evalEx$1.invoke(ReplForJupyterImpl.kt:463)", - "\tat org.jetbrains.kotlinx.jupyter.repl.impl.ReplForJupyterImpl.withEvalContext(ReplForJupyterImpl.kt:444)", - "\tat org.jetbrains.kotlinx.jupyter.repl.impl.ReplForJupyterImpl.evalEx(ReplForJupyterImpl.kt:463)", - "\tat org.jetbrains.kotlinx.jupyter.messaging.IdeCompatibleMessageRequestProcessor$processExecuteRequest$1$response$1$1.invoke(IdeCompatibleMessageRequestProcessor.kt:159)", - "\tat org.jetbrains.kotlinx.jupyter.messaging.IdeCompatibleMessageRequestProcessor$processExecuteRequest$1$response$1$1.invoke(IdeCompatibleMessageRequestProcessor.kt:158)", - "\tat org.jetbrains.kotlinx.jupyter.streams.BlockingSubstitutionEngine.withDataSubstitution(SubstitutionEngine.kt:70)", - "\tat org.jetbrains.kotlinx.jupyter.streams.StreamSubstitutionManager.withSubstitutedStreams(StreamSubstitutionManager.kt:118)", - "\tat org.jetbrains.kotlinx.jupyter.messaging.IdeCompatibleMessageRequestProcessor.withForkedIn(IdeCompatibleMessageRequestProcessor.kt:335)", - "\tat org.jetbrains.kotlinx.jupyter.messaging.IdeCompatibleMessageRequestProcessor.access$withForkedIn(IdeCompatibleMessageRequestProcessor.kt:54)", - "\tat org.jetbrains.kotlinx.jupyter.messaging.IdeCompatibleMessageRequestProcessor$evalWithIO$1$1.invoke(IdeCompatibleMessageRequestProcessor.kt:349)", - "\tat org.jetbrains.kotlinx.jupyter.streams.BlockingSubstitutionEngine.withDataSubstitution(SubstitutionEngine.kt:70)", - "\tat org.jetbrains.kotlinx.jupyter.streams.StreamSubstitutionManager.withSubstitutedStreams(StreamSubstitutionManager.kt:118)", - "\tat org.jetbrains.kotlinx.jupyter.messaging.IdeCompatibleMessageRequestProcessor.withForkedErr(IdeCompatibleMessageRequestProcessor.kt:324)", - "\tat org.jetbrains.kotlinx.jupyter.messaging.IdeCompatibleMessageRequestProcessor.access$withForkedErr(IdeCompatibleMessageRequestProcessor.kt:54)", - "\tat org.jetbrains.kotlinx.jupyter.messaging.IdeCompatibleMessageRequestProcessor$evalWithIO$1.invoke(IdeCompatibleMessageRequestProcessor.kt:348)", - "\tat org.jetbrains.kotlinx.jupyter.streams.BlockingSubstitutionEngine.withDataSubstitution(SubstitutionEngine.kt:70)", - "\tat org.jetbrains.kotlinx.jupyter.streams.StreamSubstitutionManager.withSubstitutedStreams(StreamSubstitutionManager.kt:118)", - "\tat org.jetbrains.kotlinx.jupyter.messaging.IdeCompatibleMessageRequestProcessor.withForkedOut(IdeCompatibleMessageRequestProcessor.kt:316)", - "\tat org.jetbrains.kotlinx.jupyter.messaging.IdeCompatibleMessageRequestProcessor.evalWithIO(IdeCompatibleMessageRequestProcessor.kt:347)", - "\tat org.jetbrains.kotlinx.jupyter.messaging.IdeCompatibleMessageRequestProcessor$processExecuteRequest$1$response$1.invoke(IdeCompatibleMessageRequestProcessor.kt:158)", - "\tat org.jetbrains.kotlinx.jupyter.messaging.IdeCompatibleMessageRequestProcessor$processExecuteRequest$1$response$1.invoke(IdeCompatibleMessageRequestProcessor.kt:157)", - "\tat org.jetbrains.kotlinx.jupyter.execution.JupyterExecutorImpl$Task.execute(JupyterExecutorImpl.kt:41)", - "\tat org.jetbrains.kotlinx.jupyter.execution.JupyterExecutorImpl$executorThread$1.invoke(JupyterExecutorImpl.kt:83)", - "\tat org.jetbrains.kotlinx.jupyter.execution.JupyterExecutorImpl$executorThread$1.invoke(JupyterExecutorImpl.kt:80)", - "\tat kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)", - "" - ] - } - ], - "execution_count": 5 - }, - { - "metadata": {}, - "cell_type": "code", - "source": "", - "outputs": [], - "execution_count": null - } - ], - "metadata": { - "kernelspec": { - "display_name": "Kotlin", - "language": "kotlin", - "name": "kotlin" - }, - "language_info": { - "name": "kotlin", - "version": "1.9.23", - "mimetype": "text/x-kotlin", - "file_extension": ".kt", - "pygments_lexer": "kotlin", - "codemirror_mode": "text/x-kotlin", - "nbconvert_exporter": "" - }, - "ktnbPluginMetadata": { - "projectDependencies": [ - "Amethyst.amethyst.unitTest" - ], - "projectLibraries": false - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/quartz/src/androidTest/AndroidManifest.xml b/quartz/src/androidDeviceTest/AndroidManifest.xml similarity index 100% rename from quartz/src/androidTest/AndroidManifest.xml rename to quartz/src/androidDeviceTest/AndroidManifest.xml diff --git a/quartz/src/androidTest/assets/bip39.vectors.json b/quartz/src/androidDeviceTest/assets/bip39.vectors.json similarity index 100% rename from quartz/src/androidTest/assets/bip39.vectors.json rename to quartz/src/androidDeviceTest/assets/bip39.vectors.json diff --git a/quartz/src/androidTest/assets/github_amethyst.html b/quartz/src/androidDeviceTest/assets/github_amethyst.html similarity index 100% rename from quartz/src/androidTest/assets/github_amethyst.html rename to quartz/src/androidDeviceTest/assets/github_amethyst.html diff --git a/quartz/src/androidTest/assets/nip44.vectors.json b/quartz/src/androidDeviceTest/assets/nip44.vectors.json similarity index 100% rename from quartz/src/androidTest/assets/nip44.vectors.json rename to quartz/src/androidDeviceTest/assets/nip44.vectors.json diff --git a/quartz/src/androidTest/assets/nostr_vitor_short.json b/quartz/src/androidDeviceTest/assets/nostr_vitor_short.json similarity index 100% rename from quartz/src/androidTest/assets/nostr_vitor_short.json rename to quartz/src/androidDeviceTest/assets/nostr_vitor_short.json diff --git a/quartz/src/androidTest/assets/nostr_vitor_startup_data.json b/quartz/src/androidDeviceTest/assets/nostr_vitor_startup_data.json similarity index 100% rename from quartz/src/androidTest/assets/nostr_vitor_startup_data.json rename to quartz/src/androidDeviceTest/assets/nostr_vitor_startup_data.json diff --git a/quartz/src/androidTest/assets/ovxxk2vz.jpg b/quartz/src/androidDeviceTest/assets/ovxxk2vz.jpg similarity index 100% rename from quartz/src/androidTest/assets/ovxxk2vz.jpg rename to quartz/src/androidDeviceTest/assets/ovxxk2vz.jpg diff --git a/quartz/src/androidTest/assets/relayDB.txt b/quartz/src/androidDeviceTest/assets/relayDB.txt similarity index 100% rename from quartz/src/androidTest/assets/relayDB.txt rename to quartz/src/androidDeviceTest/assets/relayDB.txt diff --git a/quartz/src/androidTest/assets/trouble_video b/quartz/src/androidDeviceTest/assets/trouble_video similarity index 100% rename from quartz/src/androidTest/assets/trouble_video rename to quartz/src/androidDeviceTest/assets/trouble_video diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/LargeDBSignatureCheck.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/LargeDBSignatureCheck.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/LargeDBSignatureCheck.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/LargeDBSignatureCheck.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/bloom/BloomFilter.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/bloom/BloomFilter.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/bloom/BloomFilter.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/bloom/BloomFilter.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/lightning/LnInvoiceUtilTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/lightning/LnInvoiceUtilTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/lightning/LnInvoiceUtilTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/lightning/LnInvoiceUtilTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/EventSigCheck.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/EventSigCheck.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/EventSigCheck.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/EventSigCheck.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/Nip01Test.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/Nip01Test.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/Nip01Test.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/Nip01Test.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/crypto/Nip01CryptoTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/crypto/Nip01CryptoTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/crypto/Nip01CryptoTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/crypto/Nip01CryptoTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/AddressableTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/AddressableTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/AddressableTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/AddressableTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/AssertUtils.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/AssertUtils.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/AssertUtils.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/AssertUtils.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/BasicTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/BasicTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/BasicTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/BasicTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/DeletionTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/DeletionTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/DeletionTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/DeletionTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/ExpirationTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/ExpirationTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/ExpirationTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/ExpirationTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/LargeDBTests.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/LargeDBTests.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/LargeDBTests.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/LargeDBTests.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/ReplaceableTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/ReplaceableTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/ReplaceableTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/ReplaceableTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/RightToVanishTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/RightToVanishTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/RightToVanishTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/RightToVanishTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/SearchTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/SearchTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/SearchTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/SearchTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip03Timestamp/ots/OtsTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/OtsTest.kt similarity index 96% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip03Timestamp/ots/OtsTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/OtsTest.kt index 0cbd18b87..1a852eaea 100644 --- a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip03Timestamp/ots/OtsTest.kt +++ b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/OtsTest.kt @@ -29,10 +29,7 @@ import junit.framework.TestCase.assertEquals import junit.framework.TestCase.assertNotNull import junit.framework.TestCase.fail import kotlinx.coroutines.runBlocking -import org.junit.Assert import org.junit.Test -import java.util.concurrent.CountDownLatch -import java.util.concurrent.TimeUnit class OtsTest { val resolver = OtsResolver() @@ -75,12 +72,8 @@ class OtsTest { val signer = NostrSignerInternal(KeyPair()) - val countDownLatch = CountDownLatch(1) - val newOts = runBlocking { signer.sign(OtsEvent.build(eventId, upgraded!!)) } - Assert.assertTrue(countDownLatch.await(1, TimeUnit.SECONDS)) - println(newOts.toJson()) println(resolver.info(newOts.otsByteArray())) @@ -91,15 +84,11 @@ class OtsTest { fun createOTSEventAndVerify() { val signer = NostrSignerInternal(KeyPair()) - val countDownLatch = CountDownLatch(1) - val ots = runBlocking { signer.sign(OtsEvent.build(otsEvent2Digest, OtsEvent.stamp(otsEvent2Digest, resolver))) } - Assert.assertTrue(countDownLatch.await(1, TimeUnit.SECONDS)) - println(ots.toJson()) println(resolver.info(ots.otsByteArray())) diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip04Dm/EncryptionTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip04Dm/EncryptionTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip04Dm/EncryptionTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip04Dm/EncryptionTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip04Dm/Nip04Test.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip04Dm/Nip04Test.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip04Dm/Nip04Test.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip04Dm/Nip04Test.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip06KeyDerivation/Bip32SeedDerivationTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Bip32SeedDerivationTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip06KeyDerivation/Bip32SeedDerivationTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Bip32SeedDerivationTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39KeyPathTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39KeyPathTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39KeyPathTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39KeyPathTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39MnemonicsTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39MnemonicsTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39MnemonicsTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39MnemonicsTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip06KeyDerivation/Nip06Test.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Nip06Test.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip06KeyDerivation/Nip06Test.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Nip06Test.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip10Notes/CitationTests.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip10Notes/CitationTests.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip10Notes/CitationTests.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip10Notes/CitationTests.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip10Notes/ThreadingTests.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip10Notes/ThreadingTests.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip10Notes/ThreadingTests.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip10Notes/ThreadingTests.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip13Pow/PoWMinerTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip13Pow/PoWMinerTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip13Pow/PoWMinerTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip13Pow/PoWMinerTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip13Pow/PoWRankEvaluatorTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip13Pow/PoWRankEvaluatorTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip13Pow/PoWRankEvaluatorTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip13Pow/PoWRankEvaluatorTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip17Dm/AESGCMTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip17Dm/AESGCMTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip17Dm/AESGCMTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip17Dm/AESGCMTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip17Dm/ChatroomKeyTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip17Dm/ChatroomKeyTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip17Dm/ChatroomKeyTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip17Dm/ChatroomKeyTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip19Bech32/NIP19EmbedTests.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip19Bech32/NIP19EmbedTests.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip19Bech32/NIP19EmbedTests.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip19Bech32/NIP19EmbedTests.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip22Comments/GeolocatedComments.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip22Comments/GeolocatedComments.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip22Comments/GeolocatedComments.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip22Comments/GeolocatedComments.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip44Encryption/Nip44v1Test.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip44Encryption/Nip44v1Test.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip44Encryption/Nip44v1Test.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip44Encryption/Nip44v1Test.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip44Encryption/Nip44v2Test.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip44Encryption/Nip44v2Test.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip44Encryption/Nip44v2Test.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip44Encryption/Nip44v2Test.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip44Encryption/TestPackageClasses.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip44Encryption/TestPackageClasses.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip44Encryption/TestPackageClasses.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip44Encryption/TestPackageClasses.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip46RemoteSigner/Nip46Test.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/Nip46Test.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip46RemoteSigner/Nip46Test.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/Nip46Test.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip49PrivKeyEnc/NIP49Test.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip49PrivKeyEnc/NIP49Test.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip49PrivKeyEnc/NIP49Test.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip49PrivKeyEnc/NIP49Test.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip55AndroidSigner/SignStringTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/SignStringTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip55AndroidSigner/SignStringTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/SignStringTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip57Zaps/PrivateZapTests.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip57Zaps/PrivateZapTests.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip57Zaps/PrivateZapTests.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip57Zaps/PrivateZapTests.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/nip59GiftWraps/GiftWrapEventTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip59GiftWraps/GiftWrapEventTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/nip59GiftWraps/GiftWrapEventTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/nip59GiftWraps/GiftWrapEventTest.kt diff --git a/quartz/src/androidTest/java/com/vitorpamplona/quartz/utils/HexEncodingTest.kt b/quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/utils/HexEncodingTest.kt similarity index 100% rename from quartz/src/androidTest/java/com/vitorpamplona/quartz/utils/HexEncodingTest.kt rename to quartz/src/androidDeviceTest/kotlin/com/vitorpamplona/quartz/utils/HexEncodingTest.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/lightning/Lud06Test.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/lightning/Lud06Test.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/lightning/Lud06Test.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/lightning/Lud06Test.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/hints/BloomFilterMurMur3Test.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/hints/BloomFilterMurMur3Test.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/hints/BloomFilterMurMur3Test.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/hints/BloomFilterMurMur3Test.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/hints/HintIndexerTest.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/hints/HintIndexerTest.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/hints/HintIndexerTest.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/hints/HintIndexerTest.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/hints/MurMur3Test.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/hints/MurMur3Test.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/hints/MurMur3Test.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/hints/MurMur3Test.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/hints/relayDB.txt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/hints/relayDB.txt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/hints/relayDB.txt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/hints/relayDB.txt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/jackson/EventDeserializerTest.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventDeserializerTest.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/jackson/EventDeserializerTest.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventDeserializerTest.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/jackson/InliningTagArrayPrettyPrinterTest.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/InliningTagArrayPrettyPrinterTest.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/jackson/InliningTagArrayPrettyPrinterTest.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/InliningTagArrayPrettyPrinterTest.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/metadata/UpdateMetadataTest.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/UpdateMetadataTest.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/metadata/UpdateMetadataTest.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/UpdateMetadataTest.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/relay/RelayUrlFormatterTest.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/relay/RelayUrlFormatterTest.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/relay/RelayUrlFormatterTest.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/relay/RelayUrlFormatterTest.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/EventDbQueryAssemblerTest.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/EventDbQueryAssemblerTest.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/EventDbQueryAssemblerTest.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/EventDbQueryAssemblerTest.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip05DnsIdentifiers/Nip05Test.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/Nip05Test.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip05DnsIdentifiers/Nip05Test.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/Nip05Test.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip19Bech32/NIP19ParserTest.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip19Bech32/NIP19ParserTest.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip19Bech32/NIP19ParserTest.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip19Bech32/NIP19ParserTest.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip19Bech32/TlvIntegerTest.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip19Bech32/TlvIntegerTest.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip19Bech32/TlvIntegerTest.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip19Bech32/TlvIntegerTest.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip30CustomEmoji/Nip30Test.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/Nip30Test.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip30CustomEmoji/Nip30Test.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/Nip30Test.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestTest.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestTest.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestTest.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestTest.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip51Lists/TagArrayExt.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip51Lists/TagArrayExt.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip51Lists/TagArrayExt.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip51Lists/TagArrayExt.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip65RelayList/RelayListRecommendationProcessorTest.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip65RelayList/RelayListRecommendationProcessorTest.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip65RelayList/RelayListRecommendationProcessorTest.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip65RelayList/RelayListRecommendationProcessorTest.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip96FileStorage/Nip96Test.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip96FileStorage/Nip96Test.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/nip96FileStorage/Nip96Test.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/nip96FileStorage/Nip96Test.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/utils/HexEncodingTest.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/utils/HexEncodingTest.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/utils/HexEncodingTest.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/utils/HexEncodingTest.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/utils/RuntimeExt.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/utils/RuntimeExt.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/utils/RuntimeExt.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/utils/RuntimeExt.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/utils/SignerUtils.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/utils/SignerUtils.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/utils/SignerUtils.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/utils/SignerUtils.kt diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/utils/StringUtilsTest.kt b/quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/utils/StringUtilsTest.kt similarity index 100% rename from quartz/src/test/java/com/vitorpamplona/quartz/utils/StringUtilsTest.kt rename to quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/utils/StringUtilsTest.kt diff --git a/quartz/src/androidMain/AndroidManifest.xml b/quartz/src/androidMain/AndroidManifest.xml new file mode 100644 index 000000000..a5918e68a --- /dev/null +++ b/quartz/src/androidMain/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/EventFactory.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/EventFactory.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/EventFactory.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/EventFactory.kt diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/Platform.android.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/Platform.android.kt new file mode 100644 index 000000000..5a6ac25b4 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/Platform.android.kt @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2025 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 + +actual fun platform() = "Android" diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/AudioHeaderEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/header/AudioHeaderEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/AudioHeaderEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/header/AudioHeaderEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/header/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/header/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/DownloadUrlTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/header/tags/DownloadUrlTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/DownloadUrlTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/header/tags/DownloadUrlTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/StreamUrlTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/header/tags/StreamUrlTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/StreamUrlTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/header/tags/StreamUrlTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/WaveformTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/header/tags/WaveformTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/WaveformTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/header/tags/WaveformTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/AudioTrackEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/track/AudioTrackEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/AudioTrackEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/track/AudioTrackEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/track/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/track/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/CoverTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/track/tags/CoverTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/CoverTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/track/tags/CoverTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/MediaTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/track/tags/MediaTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/MediaTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/track/tags/MediaTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/ParticipantTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/track/tags/ParticipantTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/ParticipantTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/track/tags/ParticipantTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/PriceTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/track/tags/PriceTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/PriceTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/track/tags/PriceTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/TypeTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/track/tags/TypeTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/TypeTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/audio/track/tags/TypeTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/bounties/BountyAddValueEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/bounties/BountyAddValueEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/bounties/BountyAddValueEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/bounties/BountyAddValueEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/bounties/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/bounties/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/bounties/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/bounties/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/bounties/RewardTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/bounties/RewardTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/bounties/RewardTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/bounties/RewardTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/bounties/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/bounties/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/bounties/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/bounties/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/decoupling/DecoupledCipher.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/decoupling/DecoupledCipher.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/decoupling/DecoupledCipher.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/decoupling/DecoupledCipher.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/decoupling/EncryptionKeyCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/decoupling/EncryptionKeyCache.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/decoupling/EncryptionKeyCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/decoupling/EncryptionKeyCache.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/decoupling/EncryptionKeyDerivation.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/decoupling/EncryptionKeyDerivation.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/decoupling/EncryptionKeyDerivation.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/decoupling/EncryptionKeyDerivation.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/decoupling/setup/EncryptionKeyListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/decoupling/setup/EncryptionKeyListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/decoupling/setup/EncryptionKeyListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/decoupling/setup/EncryptionKeyListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/decoupling/setup/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/decoupling/setup/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/decoupling/setup/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/decoupling/setup/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/decoupling/setup/tags/KeyTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/decoupling/setup/tags/KeyTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/decoupling/setup/tags/KeyTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/decoupling/setup/tags/KeyTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/edits/TextNoteModificationEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/edits/TextNoteModificationEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/edits/TextNoteModificationEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/edits/TextNoteModificationEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/chat/EphemeralChatEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/chat/EphemeralChatEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/chat/EphemeralChatEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/chat/EphemeralChatEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/chat/RoomId.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/chat/RoomId.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/chat/RoomId.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/chat/RoomId.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/chat/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/chat/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/chat/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/chat/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/chat/tags/RelayTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/chat/tags/RelayTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/chat/tags/RelayTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/chat/tags/RelayTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/chat/tags/RoomTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/chat/tags/RoomTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/chat/tags/RoomTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/chat/tags/RoomTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/db/EphemeralRoom.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/db/EphemeralRoom.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/db/EphemeralRoom.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/db/EphemeralRoom.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/db/EphemeralRoomCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/db/EphemeralRoomCache.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/db/EphemeralRoomCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/db/EphemeralRoomCache.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/list/EphemeralChatListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/list/EphemeralChatListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/list/EphemeralChatListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/list/EphemeralChatListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/list/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/list/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/list/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/list/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/list/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/list/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/list/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/list/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/list/tags/RoomIdTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/list/tags/RoomIdTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/ephemChat/list/tags/RoomIdTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/ephemChat/list/tags/RoomIdTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/forks/BaseThreadedEventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/forks/BaseThreadedEventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/forks/BaseThreadedEventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/forks/BaseThreadedEventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/forks/MarkedETagExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/forks/MarkedETagExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/forks/MarkedETagExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/forks/MarkedETagExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/inlineMetadata/Nip54InlineMetadata.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/inlineMetadata/Nip54InlineMetadata.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/inlineMetadata/Nip54InlineMetadata.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/inlineMetadata/Nip54InlineMetadata.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStoryBaseEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStoryBaseEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStoryBaseEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStoryBaseEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStoryPrologueEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStoryPrologueEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStoryPrologueEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStoryPrologueEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStoryReadingStateEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStoryReadingStateEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStoryReadingStateEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStoryReadingStateEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStorySceneEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStorySceneEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStorySceneEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/InteractiveStorySceneEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/ReadStatusTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/tags/ReadStatusTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/ReadStatusTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/tags/ReadStatusTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/RootSceneTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/tags/RootSceneTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/RootSceneTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/tags/RootSceneTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/StoryOptionTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/tags/StoryOptionTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/StoryOptionTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/interactiveStories/tags/StoryOptionTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/limits/LimitProcessor.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/limits/LimitProcessor.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/limits/LimitProcessor.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/limits/LimitProcessor.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/limits/Limits.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/limits/Limits.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/limits/Limits.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/limits/Limits.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/medical/FhirResourceEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/medical/FhirResourceEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/medical/FhirResourceEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/medical/FhirResourceEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nip95/data/FileStorageEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nip95/data/FileStorageEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/nip95/data/FileStorageEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nip95/data/FileStorageEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nip95/data/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nip95/data/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/nip95/data/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nip95/data/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nip95/header/FileStorageHeaderEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nip95/header/FileStorageHeaderEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/nip95/header/FileStorageHeaderEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nip95/header/FileStorageHeaderEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nip95/header/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nip95/header/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/nip95/header/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nip95/header/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/NNSEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nns/NNSEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/NNSEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nns/NNSEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nns/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nns/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/IPv4Tag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nns/tags/IPv4Tag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/IPv4Tag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nns/tags/IPv4Tag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/IPv6Tag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nns/tags/IPv6Tag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/IPv6Tag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nns/tags/IPv6Tag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/VersionTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nns/tags/VersionTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/VersionTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/nns/tags/VersionTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/profileGallery/GalleryListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/profileGallery/GalleryListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/profileGallery/GalleryListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/profileGallery/GalleryListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/profileGallery/ProfileGalleryEntryEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/profileGallery/ProfileGalleryEntryEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/profileGallery/ProfileGalleryEntryEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/profileGallery/ProfileGalleryEntryEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/profileGallery/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/profileGallery/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/profileGallery/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/profileGallery/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/publicMessages/PublicMessageEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/publicMessages/PublicMessageEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/publicMessages/PublicMessageEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/publicMessages/PublicMessageEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/publicMessages/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/publicMessages/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/publicMessages/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/publicMessages/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/publicMessages/tags/ReceiverTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/publicMessages/tags/ReceiverTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/publicMessages/tags/ReceiverTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/publicMessages/tags/ReceiverTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/RelationshipStatusEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/relationshipStatus/RelationshipStatusEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/RelationshipStatusEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/relationshipStatus/RelationshipStatusEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/relationshipStatus/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/relationshipStatus/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/PetNameTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/PetNameTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/PetNameTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/PetNameTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/RankTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/RankTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/RankTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/RankTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/SummaryTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/SummaryTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/SummaryTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/SummaryTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/PollNoteEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/PollNoteEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/PollNoteEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/PollNoteEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/ClosedAtTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/tags/ClosedAtTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/ClosedAtTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/tags/ClosedAtTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/ConsensusThresholdTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/tags/ConsensusThresholdTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/ConsensusThresholdTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/tags/ConsensusThresholdTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/MaximumTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/tags/MaximumTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/MaximumTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/tags/MaximumTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/MinimumTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/tags/MinimumTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/MinimumTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/tags/MinimumTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/PollOptionTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/tags/PollOptionTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/PollOptionTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/tags/PollOptionTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/lightning/LnInvoiceUtil.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/lightning/LnInvoiceUtil.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/lightning/LnInvoiceUtil.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/lightning/LnInvoiceUtil.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/lightning/LnWithdrawalUtil.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/lightning/LnWithdrawalUtil.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/lightning/LnWithdrawalUtil.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/lightning/LnWithdrawalUtil.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/lightning/Lud06.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/lightning/Lud06.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/lightning/Lud06.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/lightning/Lud06.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/AddressableEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/AddressableEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/AddressableEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/AddressableEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/BaseAddressableEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/BaseAddressableEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/BaseAddressableEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/BaseAddressableEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/BaseReplaceableEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/BaseReplaceableEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/BaseReplaceableEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/BaseReplaceableEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/Event.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/Event.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/Event.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/Event.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/HexKey.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/HexKey.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/HexKey.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/HexKey.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/IEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/IEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/IEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/IEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/Kind.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/Kind.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/Kind.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/Kind.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/Tag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/Tag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/Tag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/Tag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/TagArray.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/TagArray.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/TagArray.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/TagArray.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/TagArrayBuilder.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/TagArrayBuilder.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/TagArrayBuilder.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/TagArrayBuilder.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/crypto/DeterministicSigner.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/crypto/DeterministicSigner.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/crypto/DeterministicSigner.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/crypto/DeterministicSigner.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/crypto/EventAssembler.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/crypto/EventAssembler.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/crypto/EventAssembler.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/crypto/EventAssembler.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/crypto/EventHasher.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/crypto/EventHasher.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/crypto/EventHasher.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/crypto/EventHasher.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/crypto/KeyPair.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/crypto/KeyPair.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/crypto/KeyPair.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/crypto/KeyPair.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/crypto/Nip01.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/crypto/Nip01.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/crypto/Nip01.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/crypto/Nip01.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/EventHintBundle.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/EventHintBundle.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/EventHintBundle.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/EventHintBundle.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/HintIndexer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/HintIndexer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/HintIndexer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/HintIndexer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/HintProviders.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/HintProviders.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/HintProviders.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/HintProviders.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/bloom/BitSetExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/bloom/BitSetExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/bloom/BitSetExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/bloom/BitSetExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/bloom/BloomFilterMurMur3.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/bloom/BloomFilterMurMur3.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/bloom/BloomFilterMurMur3.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/bloom/BloomFilterMurMur3.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/bloom/MurmurHash3.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/bloom/MurmurHash3.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/bloom/MurmurHash3.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/bloom/MurmurHash3.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/types/AddressHint.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/types/AddressHint.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/types/AddressHint.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/types/AddressHint.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/types/EventIdHint.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/types/EventIdHint.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/types/EventIdHint.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/types/EventIdHint.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/types/Hint.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/types/Hint.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/types/Hint.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/types/Hint.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/types/PubKeyHint.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/types/PubKeyHint.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/types/PubKeyHint.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/hints/types/PubKeyHint.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/EventDeserializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventDeserializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/EventDeserializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventDeserializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/EventManualDeserializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventManualDeserializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/EventManualDeserializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventManualDeserializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/EventManualSerializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventManualSerializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/EventManualSerializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventManualSerializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/EventSerializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventSerializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/EventSerializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventSerializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/InliningTagArrayPrettyPrinter.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/InliningTagArrayPrettyPrinter.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/InliningTagArrayPrettyPrinter.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/InliningTagArrayPrettyPrinter.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/JacksonExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/JacksonExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/JacksonExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/JacksonExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/JsonMapper.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/JsonMapper.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/JsonMapper.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/JsonMapper.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/TagArrayDeserializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/TagArrayDeserializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/TagArrayDeserializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/TagArrayDeserializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/TagArrayManualDeserializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/TagArrayManualDeserializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/TagArrayManualDeserializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/TagArrayManualDeserializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/TagArraySerializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/TagArraySerializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/jackson/TagArraySerializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/TagArraySerializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/MetadataEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/MetadataEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/MetadataEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/MetadataEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/UserMetadata.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/UserMetadata.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/UserMetadata.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/UserMetadata.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/AboutTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/AboutTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/AboutTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/AboutTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/BannerTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/BannerTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/BannerTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/BannerTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/DisplayNameTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/DisplayNameTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/DisplayNameTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/DisplayNameTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/Lud06Tag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/Lud06Tag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/Lud06Tag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/Lud06Tag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/Lud16Tag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/Lud16Tag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/Lud16Tag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/Lud16Tag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/NameTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/NameTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/NameTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/NameTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/Nip05Tag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/Nip05Tag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/Nip05Tag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/Nip05Tag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/PictureTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/PictureTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/PictureTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/PictureTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/PronounsTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/PronounsTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/PronounsTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/PronounsTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/WebsiteTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/WebsiteTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/metadata/tags/WebsiteTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/metadata/tags/WebsiteTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/NostrClient.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/NostrClient.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/NostrClient.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/NostrClient.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/NostrClientSubscription.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/NostrClientSubscription.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/NostrClientSubscription.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/NostrClientSubscription.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/EventCollector.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/EventCollector.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/EventCollector.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/EventCollector.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/NostrClientSendAndWaitExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/NostrClientSendAndWaitExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/NostrClientSendAndWaitExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/NostrClientSendAndWaitExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/NostrClientSingleDownloadExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/NostrClientSingleDownloadExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/NostrClientSingleDownloadExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/NostrClientSingleDownloadExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayAuthenticator.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayAuthenticator.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayAuthenticator.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayAuthenticator.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayInsertConfirmationCollector.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayInsertConfirmationCollector.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayInsertConfirmationCollector.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayInsertConfirmationCollector.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayLogger.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayLogger.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayLogger.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayLogger.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayNotifier.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayNotifier.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayNotifier.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/RelayNotifier.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/listeners/IRelayClientListener.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/listeners/IRelayClientListener.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/listeners/IRelayClientListener.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/listeners/IRelayClientListener.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/listeners/RedirectRelayClientListener.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/listeners/RedirectRelayClientListener.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/listeners/RedirectRelayClientListener.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/listeners/RedirectRelayClientListener.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/pool/PoolEventOutbox.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/pool/PoolEventOutbox.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/pool/PoolEventOutbox.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/pool/PoolEventOutbox.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/pool/PoolEventOutboxRepository.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/pool/PoolEventOutboxRepository.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/pool/PoolEventOutboxRepository.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/pool/PoolEventOutboxRepository.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/pool/PoolSubscriptionRepository.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/pool/PoolSubscriptionRepository.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/pool/PoolSubscriptionRepository.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/pool/PoolSubscriptionRepository.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/pool/RelayBasedFilter.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/pool/RelayBasedFilter.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/pool/RelayBasedFilter.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/pool/RelayBasedFilter.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/pool/RelayPool.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/pool/RelayPool.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/pool/RelayPool.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/pool/RelayPool.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/single/IRelayClient.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/single/IRelayClient.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/single/IRelayClient.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/single/IRelayClient.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/single/Subscription.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/single/Subscription.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/single/Subscription.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/single/Subscription.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/single/basic/BasicRelayClient.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/single/basic/BasicRelayClient.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/single/basic/BasicRelayClient.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/single/basic/BasicRelayClient.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/single/simple/OutboxCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/single/simple/OutboxCache.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/single/simple/OutboxCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/single/simple/OutboxCache.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/single/simple/SimpleRelayClient.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/single/simple/SimpleRelayClient.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/single/simple/SimpleRelayClient.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/single/simple/SimpleRelayClient.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/stats/RelayStat.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/stats/RelayStat.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/stats/RelayStat.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/stats/RelayStat.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/stats/RelayStats.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/stats/RelayStats.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/stats/RelayStats.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/stats/RelayStats.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/subscriptions/Subscription.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/subscriptions/Subscription.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/subscriptions/Subscription.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/subscriptions/Subscription.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/subscriptions/SubscriptionController.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/subscriptions/SubscriptionController.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/subscriptions/SubscriptionController.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/subscriptions/SubscriptionController.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/subscriptions/SubscriptionStats.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/subscriptions/SubscriptionStats.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/subscriptions/SubscriptionStats.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/subscriptions/SubscriptionStats.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/AuthMessage.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/AuthMessage.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/AuthMessage.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/AuthMessage.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/ClosedMessage.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/ClosedMessage.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/ClosedMessage.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/ClosedMessage.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/EoseMessage.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/EoseMessage.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/EoseMessage.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/EoseMessage.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/EventMessage.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/EventMessage.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/EventMessage.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/EventMessage.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/Message.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/Message.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/Message.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/Message.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/NoticeMessage.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/NoticeMessage.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/NoticeMessage.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/NoticeMessage.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/NotifyMessage.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/NotifyMessage.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/NotifyMessage.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/NotifyMessage.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/OkMessage.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/OkMessage.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/OkMessage.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/OkMessage.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/ToClientParser.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/ToClientParser.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/ToClientParser.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/ToClientParser.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/AuthCmd.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/AuthCmd.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/AuthCmd.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/AuthCmd.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/CloseCmd.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/CloseCmd.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/CloseCmd.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/CloseCmd.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/Command.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/Command.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/Command.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/Command.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/CountCmd.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/CountCmd.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/CountCmd.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/CountCmd.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/EventCmd.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/EventCmd.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/EventCmd.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/EventCmd.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/ReqCmd.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/ReqCmd.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/ReqCmd.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/ReqCmd.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/ToRelayParser.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/ToRelayParser.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/ToRelayParser.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/ToRelayParser.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/filters/Filter.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/filters/Filter.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/filters/Filter.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/filters/Filter.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/filters/FilterDeserializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/filters/FilterDeserializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/filters/FilterDeserializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/filters/FilterDeserializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/filters/FilterMatcher.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/filters/FilterMatcher.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/filters/FilterMatcher.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/filters/FilterMatcher.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/filters/FilterSerializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/filters/FilterSerializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/filters/FilterSerializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/filters/FilterSerializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/normalizer/NormalizedRelayUrl.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/normalizer/NormalizedRelayUrl.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/normalizer/NormalizedRelayUrl.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/normalizer/NormalizedRelayUrl.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/normalizer/RelayUrlNormalizer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/normalizer/RelayUrlNormalizer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/normalizer/RelayUrlNormalizer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/normalizer/RelayUrlNormalizer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebSocket.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebSocket.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebSocket.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebSocket.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebSocketListener.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebSocketListener.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebSocketListener.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebSocketListener.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebsocketBuilder.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebsocketBuilder.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebsocketBuilder.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebsocketBuilder.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebsocketBuilderFactory.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebsocketBuilderFactory.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebsocketBuilderFactory.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/sockets/WebsocketBuilderFactory.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/sockets/okhttp/BasicOkHttpWebSocket.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/sockets/okhttp/BasicOkHttpWebSocket.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/sockets/okhttp/BasicOkHttpWebSocket.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/sockets/okhttp/BasicOkHttpWebSocket.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/EventTemplate.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplate.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/EventTemplate.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplate.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateDeserializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateDeserializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateDeserializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateDeserializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateManualDeserializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateManualDeserializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateManualDeserializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateManualDeserializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/NostrSigner.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/NostrSigner.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/NostrSigner.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/NostrSigner.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/NostrSignerInternal.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/NostrSignerInternal.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/NostrSignerInternal.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/NostrSignerInternal.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/NostrSignerSync.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/NostrSignerSync.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/NostrSignerSync.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/NostrSignerSync.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/SignerExceptions.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/SignerExceptions.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/SignerExceptions.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/SignerExceptions.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/caches/CacheResults.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/caches/CacheResults.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/caches/CacheResults.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/caches/CacheResults.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/caches/DecryptCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/caches/DecryptCache.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/signers/caches/DecryptCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/caches/DecryptCache.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/README.md b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/README.md similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/README.md rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/README.md diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/AddressableModule.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/AddressableModule.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/AddressableModule.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/AddressableModule.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/DeletionRequestModule.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/DeletionRequestModule.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/DeletionRequestModule.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/DeletionRequestModule.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/EphemeralModule.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/EphemeralModule.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/EphemeralModule.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/EphemeralModule.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/EventIndexesModule.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/EventIndexesModule.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/EventIndexesModule.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/EventIndexesModule.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/EventStore.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/EventStore.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/EventStore.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/EventStore.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/ExpirationModule.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/ExpirationModule.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/ExpirationModule.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/ExpirationModule.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/FullTextSearchModule.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/FullTextSearchModule.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/FullTextSearchModule.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/FullTextSearchModule.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/ReplaceableModule.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/ReplaceableModule.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/ReplaceableModule.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/ReplaceableModule.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/RightToVanishModule.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/RightToVanishModule.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/RightToVanishModule.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/RightToVanishModule.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/SQLiteEventStore.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/SQLiteEventStore.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/SQLiteEventStore.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/SQLiteEventStore.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/StatementCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/StatementCache.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/StatementCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/StatementCache.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/sql/Condition.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/sql/Condition.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/sql/Condition.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/sql/Condition.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/sql/SqlSelectionBuilder.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/sql/SqlSelectionBuilder.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/sql/SqlSelectionBuilder.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/sql/SqlSelectionBuilder.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/sql/WhereClauseBuilder.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/sql/WhereClauseBuilder.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/store/sqlite/sql/WhereClauseBuilder.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/store/sqlite/sql/WhereClauseBuilder.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/ATag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/addressables/ATag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/ATag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/addressables/ATag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/Address.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/addressables/Address.kt similarity index 77% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/Address.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/addressables/Address.kt index 8c5edc6d2..b055aab09 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/Address.kt +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/addressables/Address.kt @@ -20,6 +20,7 @@ */ package com.vitorpamplona.quartz.nip01Core.tags.addressables +import android.os.Parcel import android.os.Parcelable import android.util.Log import com.vitorpamplona.quartz.nip01Core.core.HexKey @@ -29,9 +30,7 @@ import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress import com.vitorpamplona.quartz.utils.Hex import com.vitorpamplona.quartz.utils.bytesUsedInMemory import com.vitorpamplona.quartz.utils.pointerSizeInBytes -import kotlinx.parcelize.Parcelize -@Parcelize data class Address( val kind: Kind, val pubKeyHex: HexKey, @@ -61,6 +60,19 @@ data class Address( } companion object { + // ----------- + // Manual Parcelable implementation to avoid issues between kmp and the parcelize plugin + // ----------- + @JvmField + val CREATOR = + object : Parcelable.Creator
{ + // Create an instance from the Parcel + override fun createFromParcel(parcel: Parcel): Address = Address(parcel) + + // Create a new array of the Parcelable class + override fun newArray(size: Int): Array = arrayOfNulls(size) + } + fun assemble( kind: Int, pubKeyHex: HexKey, @@ -99,4 +111,25 @@ data class Address( kind: String, ) = addressId.startsWith(kind) && addressId[kind.length] == ':' } + + // ----------- + // Manual Parcelable implementation to avoid issues between kmp and the parcelize plugin + // ----------- + override fun writeToParcel( + parcel: Parcel, + flags: Int, + ) { + parcel.writeInt(kind) + parcel.writeString(pubKeyHex) + parcel.writeString(dTag) + } + + override fun describeContents() = 0 + + // 4. Primary constructor for deserialization + constructor(parcel: Parcel) : this( + kind = parcel.readInt(), + pubKeyHex = parcel.readString() ?: "", + dTag = parcel.readString() ?: "", + ) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/addressables/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/addressables/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/addressables/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/addressables/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/addressables/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/addressables/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/dTags/DTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/dTags/DTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/dTags/DTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/dTags/DTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/dTags/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/dTags/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/dTags/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/dTags/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/dTags/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/dTags/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/dTags/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/dTags/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/dTags/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/dTags/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/dTags/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/dTags/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/ETag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/events/ETag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/ETag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/events/ETag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/events/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/events/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/EventReference.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/events/EventReference.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/EventReference.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/events/EventReference.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/GenericETag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/events/GenericETag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/GenericETag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/events/GenericETag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/events/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/events/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/events/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/events/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/geohash/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/geohash/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/geohash/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/geohash/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/geohash/GeoHashTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/geohash/GeoHashTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/geohash/GeoHashTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/geohash/GeoHashTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/geohash/GeohashPrecision.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/geohash/GeohashPrecision.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/geohash/GeohashPrecision.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/geohash/GeohashPrecision.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/geohash/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/geohash/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/geohash/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/geohash/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/geohash/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/geohash/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/geohash/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/geohash/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/hashtags/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/hashtags/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/hashtags/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/hashtags/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/hashtags/HashtagTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/hashtags/HashtagTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/hashtags/HashtagTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/hashtags/HashtagTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/hashtags/MipMapHashTags.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/hashtags/MipMapHashTags.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/hashtags/MipMapHashTags.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/hashtags/MipMapHashTags.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/hashtags/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/hashtags/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/hashtags/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/hashtags/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/hashtags/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/hashtags/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/hashtags/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/hashtags/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/kinds/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/kinds/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/kinds/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/kinds/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/kinds/KindTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/kinds/KindTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/kinds/KindTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/kinds/KindTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/kinds/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/kinds/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/kinds/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/kinds/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/kinds/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/kinds/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/kinds/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/kinds/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/EntityExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/people/EntityExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/EntityExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/people/EntityExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/people/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/people/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/PTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/people/PTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/PTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/people/PTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/PubKeyReferenceTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/people/PubKeyReferenceTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/PubKeyReferenceTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/people/PubKeyReferenceTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/people/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/people/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/people/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/people/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/publishedAt/PublishedAtProvider.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/publishedAt/PublishedAtProvider.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/publishedAt/PublishedAtProvider.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/publishedAt/PublishedAtProvider.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/references/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/references/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/references/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/references/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/references/ReferenceTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/references/ReferenceTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/references/ReferenceTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/references/ReferenceTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/references/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/references/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/references/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/references/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/references/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/references/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/references/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip01Core/tags/references/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/ContactListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip02FollowList/ContactListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/ContactListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip02FollowList/ContactListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/ImmutableListOfLists.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip02FollowList/ImmutableListOfLists.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/ImmutableListOfLists.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip02FollowList/ImmutableListOfLists.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/RelaySet.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip02FollowList/RelaySet.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/RelaySet.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip02FollowList/RelaySet.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/tags/ContactTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip02FollowList/tags/ContactTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/tags/ContactTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip02FollowList/tags/ContactTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/OtsEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/OtsEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/OtsEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/OtsEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/OtsResolver.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/OtsResolver.kt similarity index 90% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/OtsResolver.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/OtsResolver.kt index 4d560b1e9..169f282e0 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/OtsResolver.kt +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/OtsResolver.kt @@ -22,14 +22,14 @@ package com.vitorpamplona.quartz.nip03Timestamp import android.util.Log import com.vitorpamplona.quartz.nip03Timestamp.ots.BitcoinExplorer -import com.vitorpamplona.quartz.nip03Timestamp.ots.BlockstreamExplorer import com.vitorpamplona.quartz.nip03Timestamp.ots.CalendarBuilder -import com.vitorpamplona.quartz.nip03Timestamp.ots.CalendarPureJavaBuilder import com.vitorpamplona.quartz.nip03Timestamp.ots.DetachedTimestampFile import com.vitorpamplona.quartz.nip03Timestamp.ots.Hash import com.vitorpamplona.quartz.nip03Timestamp.ots.OpenTimestamps import com.vitorpamplona.quartz.nip03Timestamp.ots.VerifyResult import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.UrlException +import com.vitorpamplona.quartz.nip03Timestamp.ots.http.BlockstreamExplorer +import com.vitorpamplona.quartz.nip03Timestamp.ots.http.CalendarPureJavaBuilder import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpSHA256 import kotlinx.coroutines.CancellationException @@ -42,10 +42,10 @@ class OtsResolver( fun info(otsState: ByteArray): String = ots.info(DetachedTimestampFile.deserialize(otsState)) fun stamp(data: ByteArray): ByteArray { - val hash = Hash(data, OpSHA256._TAG) + val hash = Hash(data, OpSHA256.TAG) val file = DetachedTimestampFile.from(hash) val timestamp = ots.stamp(file) - val detachedToSerialize = DetachedTimestampFile(hash.getOp(), timestamp) + val detachedToSerialize = DetachedTimestampFile(hash.op, timestamp) return detachedToSerialize.serialize() } @@ -78,7 +78,7 @@ class OtsResolver( ): VerificationState { try { val result = ots.verify(detachedOts, data) - if (result == null || result.isEmpty()) { + if (result.isEmpty()) { return VerificationState.Error("Verification hashmap is empty") } else { val time = result.get(VerifyResult.Chains.BITCOIN)?.timestamp @@ -90,7 +90,7 @@ class OtsResolver( } } catch (e: Exception) { if (e is CancellationException) throw e - Log.e("OpenTimeStamps", "Failed to verify", e) + Log.w("OpenTimeStamps", "Failed to verify", e) return if (e is UrlException) { VerificationState.NetworkError(e.message ?: e.cause?.message ?: "Failed to verify") } else { diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/OtsResolverBuilder.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/OtsResolverBuilder.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/OtsResolverBuilder.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/OtsResolverBuilder.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/VerificationState.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/VerificationState.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/VerificationState.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/VerificationState.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/VerificationStateCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/VerificationStateCache.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/VerificationStateCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/VerificationStateCache.kt diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/BitcoinExplorer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/BitcoinExplorer.kt new file mode 100644 index 000000000..a3c094c6f --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/BitcoinExplorer.kt @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots + +interface BitcoinExplorer { + /** + * Retrieve the block information from the block hash. + * + * @param hash Hash of the block. + * @return the blockheader of the hash + * @throws Exception desc + */ + @Throws(Exception::class) + fun block(hash: String): BlockHeader + + /** + * Retrieve the block hash from the block height. + * + * @param height Height of the block. + * @return the hash of the block at height height + * @throws Exception desc + */ + @Throws(Exception::class) + fun blockHash(height: Int): String +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/BlockHeader.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/BlockHeader.kt new file mode 100644 index 000000000..ca4235dfc --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/BlockHeader.kt @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots + +data class BlockHeader( + val merkleRoot: String, + val blockHash: String, + val time: String, +) { + fun getTime(): Long = time.toLong() +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarBuilder.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarBuilder.kt new file mode 100644 index 000000000..5b317e2bd --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarBuilder.kt @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots + +interface CalendarBuilder { + fun newSyncCalendar(url: String): ICalendar + + fun newAsyncCalendar( + url: String, + digest: ByteArray, + ): ICalendarAsyncSubmit +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/DetachedTimestampFile.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/DetachedTimestampFile.kt new file mode 100644 index 000000000..52699b94e --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/DetachedTimestampFile.kt @@ -0,0 +1,272 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots + +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.Op +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpCrypto +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpSHA256 +import java.io.File +import java.io.IOException +import java.io.InputStream +import java.security.NoSuchAlgorithmException + +/** + * Class representing Detached com.vitorpamplona.quartz.ots.Timestamp File. + * A file containing a timestamp for another file. + * Contains a timestamp, along with a header and the digest of the file. + */ +class DetachedTimestampFile( + val fileHashOp: Op, + val timestamp: Timestamp, +) { + /** + * The digest of the file that was timestamped. + * + * @return The message inside the timestamp. + */ + fun fileDigest(): ByteArray? = this.timestamp.digest + + /** + * Serialize a com.vitorpamplona.quartz.ots.Timestamp File. + * + * @param ctx The stream serialization context. + */ + fun serialize(ctx: StreamSerializationContext) { + ctx.writeBytes(HEADER_MAGIC) + ctx.writeVaruint(MAJOR_VERSION.toInt()) + this.fileHashOp.serialize(ctx) + ctx.writeBytes(this.timestamp.digest) + this.timestamp.serialize(ctx) + } + + /** + * Serialize a com.vitorpamplona.quartz.ots.Timestamp File. + * + * @return The byte array of serialized data. + */ + fun serialize(): ByteArray { + val ctx = StreamSerializationContext() + this.serialize(ctx) + + return ctx.output + } + + /** + * Print the object. + * + * @return The output. + */ + override fun toString(): String { + var output = "com.vitorpamplona.quartz.ots.DetachedTimestampFile\n" + output += "fileHashOp: " + this.fileHashOp.toString() + '\n' + output += "timestamp: " + this.timestamp.toString() + '\n' + + return output + } + + companion object { + /** + * Header magic bytes Designed to be give the user some information in a hexdump, while being + * identified as 'data' by the file utility. + * + * @default \x00OpenTimestamps\x00\x00Proof\x00\xbf\x89\xe2\xe8\x84\xe8\x92\x94 + */ + val HEADER_MAGIC: ByteArray = + byteArrayOf( + 0x00.toByte(), + 0x4f.toByte(), + 0x70.toByte(), + 0x65.toByte(), + 0x6e.toByte(), + 0x54.toByte(), + 0x69.toByte(), + 0x6d.toByte(), + 0x65.toByte(), + 0x73.toByte(), + 0x74.toByte(), + 0x61.toByte(), + 0x6d.toByte(), + 0x70.toByte(), + 0x73.toByte(), + 0x00.toByte(), + 0x00.toByte(), + 0x50.toByte(), + 0x72.toByte(), + 0x6f.toByte(), + 0x6f.toByte(), + 0x66.toByte(), + 0x00.toByte(), + 0xbf.toByte(), + 0x89.toByte(), + 0xe2.toByte(), + 0xe8.toByte(), + 0x84.toByte(), + 0xe8.toByte(), + 0x92.toByte(), + 0x94.toByte(), + ) + + /** + * While the git commit timestamps have a minor version, probably better to + * leave it out here: unlike Git commits round-tripping is an issue when + * timestamps are upgraded, and we could end up with bugs related to not + * saving/updating minor version numbers correctly. + * + * @default 1 + */ + const val MAJOR_VERSION: Byte = 1 + + /** + * Deserialize a com.vitorpamplona.quartz.ots.Timestamp File. + * + * @param ctx The stream deserialization context. + * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. + */ + @Throws(DeserializationException::class) + fun deserialize(ctx: StreamDeserializationContext): DetachedTimestampFile { + ctx.assertMagic(HEADER_MAGIC) + ctx.readVaruint() + + val fileHashOp = Op.deserialize(ctx) as OpCrypto + val fileHash = ctx.readBytes(fileHashOp.digestLength()) + val timestamp = Timestamp.deserialize(ctx, fileHash) + + ctx.assertEof() + + return DetachedTimestampFile(fileHashOp, timestamp) + } + + /** + * Deserialize a com.vitorpamplona.quartz.ots.Timestamp File. + * + * @param ots The byte array of deserialization DetachedFileTimestamped. + * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. + */ + @Throws(DeserializationException::class) + fun deserialize(ots: ByteArray): DetachedTimestampFile { + val ctx = StreamDeserializationContext(ots) + + return deserialize(ctx) + } + + /** + * Read the Detached com.vitorpamplona.quartz.ots.Timestamp File from bytes. + * + * @param fileHashOp The file hash operation. + * @param ctx The stream deserialization context. + * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. + * @throws NoSuchAlgorithmException desc + */ + @Throws(NoSuchAlgorithmException::class) + fun from( + fileHashOp: OpCrypto, + ctx: StreamDeserializationContext, + ): DetachedTimestampFile { + val fdHash = fileHashOp.hashFd(ctx) + + return DetachedTimestampFile(fileHashOp, Timestamp(fdHash)) + } + + /** + * Read the Detached com.vitorpamplona.quartz.ots.Timestamp File from bytes. + * + * @param fileHashOp The file hash operation. + * @param bytes The byte array of data to hash + * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. + * @throws NoSuchAlgorithmException desc + */ + @Throws(Exception::class) + fun from( + fileHashOp: OpCrypto, + bytes: ByteArray, + ): DetachedTimestampFile { + val fdHash = fileHashOp.hashFd(bytes) + + return DetachedTimestampFile(fileHashOp, Timestamp(fdHash)) + } + + /** + * Read the Detached com.vitorpamplona.quartz.ots.Timestamp File from hash. + * + * @param inputStream The InputStream of the file to hash + * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. + * @throws Exception if the input stream is null + */ + @Throws(Exception::class) + fun from(inputStream: InputStream): DetachedTimestampFile { + try { + val fileTimestamp: DetachedTimestampFile = + from(OpSHA256(), inputStream) // Read from file reader stream + return fileTimestamp + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + throw Exception() + } + } + + /** + * Read the Detached com.vitorpamplona.quartz.ots.Timestamp File from InputStream. + * + * @param fileHashOp The file hash operation. + * @param inputStream The input stream file. + * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. + * @throws IOException desc + * @throws NoSuchAlgorithmException desc + */ + @Throws(IOException::class, NoSuchAlgorithmException::class) + fun from( + fileHashOp: OpCrypto, + inputStream: InputStream, + ): DetachedTimestampFile { + val fdHash = fileHashOp.hashFd(inputStream) + + return DetachedTimestampFile(fileHashOp, Timestamp(fdHash)) + } + + /** + * Read the Detached com.vitorpamplona.quartz.ots.Timestamp File from hash. + * + * @param hash The hash of the file. + * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. + */ + fun from(hash: Hash): DetachedTimestampFile = DetachedTimestampFile(hash.op, Timestamp(hash.value)) + + /** + * Read the Detached com.vitorpamplona.quartz.ots.Timestamp File from File. + * + * @param fileHashOp The file hash operation. + * @param file The hash file. + * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. + * @throws IOException desc + * @throws NoSuchAlgorithmException desc + */ + @Throws(IOException::class, NoSuchAlgorithmException::class) + fun from( + fileHashOp: OpCrypto, + file: File?, + ): DetachedTimestampFile { + val fdHash = fileHashOp.hashFd(file) + + return DetachedTimestampFile(fileHashOp, Timestamp(fdHash)) + } + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/Hash.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/Hash.kt new file mode 100644 index 000000000..0dccda379 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/Hash.kt @@ -0,0 +1,170 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots + +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpCrypto +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpKECCAK256 +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpRIPEMD160 +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpSHA1 +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpSHA256 +import com.vitorpamplona.quartz.utils.Hex.encode +import java.io.File +import java.io.IOException +import java.io.InputStream +import java.security.NoSuchAlgorithmException + +/** + * Create a Hash object. + * + * @param value - The byte array of the hash + * @param algorithm - The hashlib tag of crypto operation + */ +class Hash( + val value: ByteArray, + val algorithm: Byte, +) { + /** + * Create a Hash object. + * + * @param value - The byte array of the hash + * @param label - The hashlib name of crypto operation + */ + constructor(value: ByteArray, label: String) : this(value, getOp(label).tag()) + + val op: OpCrypto = + when (this.algorithm) { + OpSHA1.TAG -> OpSHA1() + OpSHA256.TAG -> OpSHA256() + OpRIPEMD160.TAG -> OpRIPEMD160() + OpKECCAK256.TAG -> OpKECCAK256() + else -> OpSHA256() + } + + /** + * Print the object. + * + * @return The output. + */ + override fun toString(): String { + var output = "com.vitorpamplona.quartz.ots.Hash\n" + output += "algorithm: " + this.op.hashLibName() + '\n' + output += "value: " + encode(this.value) + '\n' + + return output + } + + companion object { + /** + * Get Crypto operation from hashlib tag. + * + * @param algorithm The hashlib tag. + * @return The generated com.vitorpamplona.quartz.ots.OpCrypto object. + */ + fun getOp(algorithm: Byte): OpCrypto = + when (algorithm) { + OpSHA1.TAG -> OpSHA1() + OpSHA256.TAG -> OpSHA256() + OpRIPEMD160.TAG -> OpRIPEMD160() + OpKECCAK256.TAG -> OpKECCAK256() + else -> OpSHA256() + } + + /** + * Get Crypto operation from hashlib name. + * + * @param label The hashlib name. + * @return The generated com.vitorpamplona.quartz.ots.OpCrypto object. + */ + fun getOp(label: String): OpCrypto { + if (label.lowercase() == OpSHA1().tagName()) { + return OpSHA1() + } else if (label.lowercase() == OpSHA256().tagName()) { + return OpSHA256() + } else if (label.lowercase() == OpRIPEMD160().tagName()) { + return OpRIPEMD160() + } else if (label.lowercase() == OpKECCAK256().tagName()) { + return OpKECCAK256() + } + + return OpSHA256() + } + + /** + * Build hash from data. + * + * @param bytes The byte array of data to hash. + * @param algorithm The hash file. + * @return The generated com.vitorpamplona.quartz.ots.Hash object. + * @throws IOException desc + * @throws NoSuchAlgorithmException desc + */ + @Throws(IOException::class, NoSuchAlgorithmException::class) + fun from( + bytes: ByteArray, + algorithm: Byte, + ): Hash { + val opCrypto: OpCrypto = getOp(algorithm) + val value = opCrypto.hashFd(bytes) + + return Hash(value, algorithm) + } + + /** + * Build hash from File. + * + * @param file The File of data to hash. + * @param algorithm The hash file. + * @return The generated com.vitorpamplona.quartz.ots.Hash object. + * @throws IOException desc + * @throws NoSuchAlgorithmException desc + */ + @Throws(IOException::class, NoSuchAlgorithmException::class) + fun from( + file: File?, + algorithm: Byte, + ): Hash { + val opCrypto: OpCrypto = getOp(algorithm) + val value = opCrypto.hashFd(file) + + return Hash(value, algorithm) + } + + /** + * Build hash from InputStream. + * + * @param inputStream The InputStream of data to hash. + * @param algorithm The hash file. + * @return The generated com.vitorpamplona.quartz.ots.Hash object. + * @throws IOException desc + * @throws NoSuchAlgorithmException desc + */ + @Throws(IOException::class, NoSuchAlgorithmException::class) + fun from( + inputStream: InputStream, + algorithm: Byte, + ): Hash { + val opCrypto: OpCrypto = getOp(algorithm) + val value = opCrypto.hashFd(inputStream) + + return Hash(value, algorithm) + } + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendar.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendar.kt new file mode 100644 index 000000000..8ddc0d9c5 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendar.kt @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots + +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.CommitmentNotFoundException +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.ExceededSizeException +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.UrlException + +interface ICalendar { + @Throws(ExceededSizeException::class, UrlException::class, DeserializationException::class) + fun submit(digest: ByteArray): Timestamp + + @Throws( + DeserializationException::class, + ExceededSizeException::class, + CommitmentNotFoundException::class, + UrlException::class, + ) + fun getTimestamp(commitment: ByteArray): Timestamp +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendarAsyncSubmit.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendarAsyncSubmit.kt new file mode 100644 index 000000000..b80e2238d --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendarAsyncSubmit.kt @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots + +import java.util.Optional +import java.util.concurrent.Callable + +interface ICalendarAsyncSubmit : Callable> { + @Throws(Exception::class) + override fun call(): Optional +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/Merkle.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/Merkle.kt new file mode 100644 index 000000000..4d96a22d7 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/Merkle.kt @@ -0,0 +1,118 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots + +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpAppend +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpPrepend +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpSHA256 + +/** + * Utility functions for merkle trees + */ +object Merkle { + /** + * Concatenate left and right, then perform a unary operation on them left and right can be either timestamps or bytes. + * Appropriate intermediary append/prepend operations will be created as needed for left and right. + * + * @param left the left timestamp parameter + * @param right the right timestamp parameter + * @return the concatenation of left and right + */ + fun catThenUnaryOp( + left: Timestamp, + right: Timestamp, + ): Timestamp? { + // rightPrependStamp = right.ops.add(OpPrepend(left.msg)) + val rightPrependStamp = right.add(OpPrepend(left.digest)) + + // Left and right should produce the same thing, so we can set the timestamp of the left to the right. + // left.ops[OpAppend(right.msg)] = right_prepend_stamp + // leftAppendStamp = left.ops.add(OpAppend(right.msg)) + // Timestamp leftPrependStamp = left.add(new OpAppend(right.msg)); + left.ops.put(OpAppend(right.digest), rightPrependStamp!!) + + // return rightPrependStamp.ops.add(unaryOpCls()) + val res = rightPrependStamp.add(OpSHA256()) + return res + } + + fun catSha256( + left: Timestamp, + right: Timestamp, + ): Timestamp = catThenUnaryOp(left, right)!! + + fun catSha256d( + left: Timestamp, + right: Timestamp, + ): Timestamp? { + val sha256Timestamp = catSha256(left, right) + // res = sha256Timestamp.ops.add(OpSHA256()); + val res = sha256Timestamp.add(OpSHA256()) + return res + } + + /** + * Merkelize a set of timestamps. + * A merkle tree of all the timestamps is built in-place using binop() to + * timestamp each pair of timestamps. The exact algorithm used is structurally + * identical to a merkle-mountain-range, although leaf sums aren't committed. + * As this function is under the consensus-critical core, it's guaranteed that + * the algorithm will not be changed in the future. + * + * @param timestamps a list of timestamps + * @return the timestamp for the tip of the tree. + */ + fun makeMerkleTree(timestamps: MutableList): Timestamp? { + var stamps = timestamps + var prevStamp: Timestamp? = null + var exit = false + + while (!exit) { + if (stamps.isNotEmpty()) { + prevStamp = stamps[0] + } + + val subStamps: MutableList = stamps.subList(1, stamps.size) + val nextStamps: MutableList = ArrayList() + + for (stamp in subStamps) { + if (prevStamp == null) { + prevStamp = stamp + } else { + nextStamps.add(catSha256(prevStamp, stamp)) + prevStamp = null + } + } + + if (nextStamps.size == 0) { + exit = true + } else { + if (prevStamp != null) { + nextStamps.add(prevStamp) + } + + stamps = nextStamps + } + } + + return prevStamp + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/OpenTimestamps.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/OpenTimestamps.kt new file mode 100644 index 000000000..c99f5c6fa --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/OpenTimestamps.kt @@ -0,0 +1,457 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots + +import android.util.Log +import com.vitorpamplona.quartz.nip01Core.core.toHexKey +import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils.arrayReverse +import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils.randBytes +import com.vitorpamplona.quartz.nip03Timestamp.ots.VerifyResult.Chains +import com.vitorpamplona.quartz.nip03Timestamp.ots.attestation.BitcoinBlockHeaderAttestation +import com.vitorpamplona.quartz.nip03Timestamp.ots.attestation.PendingAttestation +import com.vitorpamplona.quartz.nip03Timestamp.ots.attestation.TimeAttestation +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.VerificationException +import com.vitorpamplona.quartz.nip03Timestamp.ots.http.Calendar +import com.vitorpamplona.quartz.nip03Timestamp.ots.http.CalendarAsyncSubmit +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpAppend +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpCrypto +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpSHA256 +import com.vitorpamplona.quartz.utils.Hex +import java.io.IOException +import java.nio.charset.StandardCharsets +import java.security.NoSuchAlgorithmException +import java.util.Optional +import java.util.concurrent.ArrayBlockingQueue +import java.util.concurrent.Executors + +/** + * The main class for timestamp operations. + */ +class OpenTimestamps( + var explorer: BitcoinExplorer, + var calBuilder: CalendarBuilder?, +) { + /** + * Show information on a detached timestamp with verbose option. + * + * @param detachedTimestampFile The DetachedTimestampFile ots. + * @param verbose Show verbose output. + * @return the string representation of the timestamp. + */ + fun info( + detachedTimestampFile: DetachedTimestampFile?, + verbose: Boolean = false, + ): String { + if (detachedTimestampFile == null) { + return "No ots file" + } + + val fileHash = + detachedTimestampFile.timestamp.digest + .toHexKey() + .lowercase() + val hashOp = (detachedTimestampFile.fileHashOp as OpCrypto).tagName() + + val firstLine = "File $hashOp hash: $fileHash\n" + + return firstLine + "Timestamp:\n" + detachedTimestampFile.timestamp.strTree(0, verbose) + } + + /** + * Show information on a timestamp. + * + * @param timestamp The timestamp buffered. + * @return the string representation of the timestamp. + */ + fun info(timestamp: Timestamp?): String { + if (timestamp == null) { + return "No timestamp" + } + + val fileHash = timestamp.digest.toHexKey().lowercase() + val firstLine = "Hash: $fileHash\n" + + return firstLine + "Timestamp:\n" + timestamp.strTree(0) + } + + /** + * Create timestamp with the aid of a remote calendar. May be specified multiple times. + * + * @param fileTimestamp The timestamp to stamp. + * @param calendarsUrl The list of calendar urls. + * @param m The number of calendar to use. + * @return The plain array buffer of stamped. + * @throws IOException if fileTimestamp is not valid, or the stamp procedure fails. + */ + @Throws(IOException::class) + fun stamp( + fileTimestamp: DetachedTimestampFile?, + calendarsUrl: MutableList = mutableListOf(), + m: Int? = 0, + ): Timestamp { + val fileTimestamps: MutableList = ArrayList() + fileTimestamps.add(fileTimestamp!!) + + return stamp(fileTimestamps, calendarsUrl, m) + } + + /** + * Create timestamp with the aid of a remote calendar. May be specified multiple times. + * + * @param fileTimestamps The list of timestamp to stamp. + * @param calendarsUrl The list of calendar urls. + * @param m The number of calendar to use. + * @return The plain array buffer of stamped. + * @throws IOException if fileTimestamp is not valid, or the stamp procedure fails. + */ + @Throws(IOException::class) + fun stamp( + fileTimestamps: MutableList, + calendarsUrl: MutableList, + m: Int?, + ): Timestamp { + // Parse parameters + var calendarsUrl = calendarsUrl + var m = m + if (fileTimestamps.isEmpty()) { + throw IOException() + } + + if (calendarsUrl.isEmpty()) { + calendarsUrl = ArrayList() + calendarsUrl.add("https://alice.btc.calendar.opentimestamps.org") + calendarsUrl.add("https://bob.btc.calendar.opentimestamps.org") + calendarsUrl.add("https://finney.calendar.eternitywall.com") + } + + if (m == null || m <= 0) { + if (calendarsUrl.size == 0) { + m = 2 + } else if (calendarsUrl.size == 1) { + m = 1 + } else { + m = calendarsUrl.size + } + } + + if (m < 0 || m > calendarsUrl.size) { + Log.e( + "OpenTimestamp", + "m cannot be greater than available calendar neither less or equal 0", + ) + throw IOException() + } + + // Build markle tree + val merkleTip = makeMerkleTree(fileTimestamps) + + // Stamping + val resultTimestamp = create(merkleTip, calendarsUrl, m) + + // Result of timestamp serialization + if (fileTimestamps.size == 1) { + return fileTimestamps.get(0).timestamp + } else { + return merkleTip + } + } + + /** + * Create a timestamp + * + * @param timestamp The timestamp. + * @param calendarUrls List of calendar's to use. + * @param m Number of calendars to use. + * @return The created timestamp. + */ + private fun create( + timestamp: Timestamp, + calendarUrls: MutableList, + m: Int, + ): Timestamp { + val capacity = calendarUrls.size + val executor = Executors.newFixedThreadPool(4) + val queue = ArrayBlockingQueue>(capacity) + + // Submit to all public calendars + for (calendarUrl in calendarUrls) { + Log.i("OpenTimestamps", "Submitting to remote calendar $calendarUrl") + + try { + val task = CalendarAsyncSubmit(calendarUrl, timestamp.digest) + task.setQueue(queue) + executor.submit>(task) + } catch (e: Exception) { + e.printStackTrace() + } + } + + var count = 0 + + count = 0 + while (count < capacity && count < m) { + try { + val optionalStamp = queue.take() + + if (optionalStamp.isPresent()) { + try { + val time = optionalStamp.get() + timestamp.merge(time) + Log.i("Open", "" + timestamp.attestations.size) + } catch (e: Exception) { + e.printStackTrace() + } + } + } catch (e: Exception) { + e.printStackTrace() + } + count++ + } + + if (count < m) { + Log.e( + "OpenTimestamp", + "Failed to create timestamp: requested " + m.toString() + " attestation" + (if (m > 1) "s" else "") + " but received only " + count.toString(), + ) + } + + // shut down the executor service now + executor.shutdown() + + return timestamp + } + + /** + * Make Merkle Tree of detached timestamps. + * + * @param fileTimestamps The list of DetachedTimestampFile. + * @return merkle tip timestamp. + */ + fun makeMerkleTree(fileTimestamps: MutableList): Timestamp { + val merkleRoots: MutableList = ArrayList() + + for (fileTimestamp in fileTimestamps) { + var bytesRandom16 = ByteArray(16) + + try { + bytesRandom16 = randBytes(16) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } + + val nonceAppendedStamp = fileTimestamp.timestamp.add(OpAppend(bytesRandom16)) + val merkleRoot = nonceAppendedStamp.add(OpSHA256()) + merkleRoots.add(merkleRoot) + } + + val merkleTip: Timestamp = Merkle.makeMerkleTree(merkleRoots)!! + return merkleTip + } + + /** + * Compare and verify a detached timestamp. + * + * @param ots The DetachedTimestampFile containing the proof to verify. + * @param diggest The hash of the stamped file, in bytes + * @return Hashmap of block heights and timestamps indexed by chain: timestamp in seconds from 1 January 1970. + * @throws Exception if the verification procedure fails. + */ + @Throws(Exception::class) + fun verify( + ots: DetachedTimestampFile, + diggest: ByteArray, + ): HashMap { + if (!ots.fileDigest().contentEquals(diggest)) { + Log.e("OpenTimestamp", "Expected digest " + Hex.encode(ots.fileDigest()!!).lowercase()) + Log.e("OpenTimestamp", "File does not match original!") + throw Exception("File does not match original!") + } + + return verify(ots.timestamp) + } + + /** + * Verify a timestamp. + * + * @param timestamp The timestamp. + * @return HashMap of block heights and timestamps indexed by chain: timestamp in seconds from 1 January 1970. + * @throws Exception if the verification procedure fails. + */ + @Throws(Exception::class) + fun verify(timestamp: Timestamp): HashMap { + val verifyResults = HashMap() + + for (item in timestamp.allAttestations().entries) { + val msg = item.key + val attestation: TimeAttestation? = item.value + var verifyResult: VerifyResult? = null + + try { + if (attestation is BitcoinBlockHeaderAttestation) { + val time = verify(attestation, msg) + val height = attestation.height + verifyResult = VerifyResult(time, height) + + val currentResults = verifyResults.get(Chains.BITCOIN) + + if (currentResults != null) { + if (verifyResult.height < currentResults.height) { + verifyResults.put(Chains.BITCOIN, verifyResult) + } + } else { + verifyResults.put(Chains.BITCOIN, verifyResult) + } + } + } catch (e: VerificationException) { + throw e + } catch (e: Exception) { + Log.e("OpenTimestamp", "Verification failed: " + e.message) + throw e + } + } + return verifyResults + } + + /** + * Verify an Bitcoin Block Header Attestation. + * if the node is not reachable or it fails, uses Lite-client verification. + * + * @param attestation The BitcoinBlockHeaderAttestation attestation. + * @param msg The digest to verify. + * @return The unix timestamp in seconds from 1 January 1970. + * @throws VerificationException if it doesn't check the merkle root of the block. + * @throws Exception if the verification procedure fails. + */ + @Throws(VerificationException::class, Exception::class) + fun verify( + attestation: BitcoinBlockHeaderAttestation, + msg: ByteArray, + ): Long? { + val height = attestation.height + val blockInfo: BlockHeader? + + try { + val blockHash = explorer.blockHash(height) + blockInfo = explorer.block(blockHash) + Log.i( + "OpenTimestamps", + "Lite-client verification, assuming block $blockHash is valid", + ) + } catch (e2: Exception) { + e2.printStackTrace() + throw e2 + } + + return attestation.verifyAgainstBlockheader(arrayReverse(msg), blockInfo) + } + + /** + * Upgrade a timestamp. + * + * @param detachedTimestamp The DetachedTimestampFile containing the proof to verify. + * @return a boolean representing if the timestamp has changed. + * @throws Exception if the upgrading procedure fails. + */ + @Throws(Exception::class) + fun upgrade(detachedTimestamp: DetachedTimestampFile): Boolean { + // Upgrade timestamp + val changed = upgrade(detachedTimestamp.timestamp) + return changed + } + + /** + * Attempt to upgrade an incomplete timestamp to make it verifiable. + * Note that this means if the timestamp that is already complete, False will be returned as nothing has changed. + * + * @param timestamp The timestamp to upgrade. + * @return a boolean representing if the timestamp has changed. + * @throws Exception if the upgrading procedure fails. + */ + @Throws(Exception::class) + fun upgrade(timestamp: Timestamp): Boolean { + // Check remote calendars for upgrades. + // This time we only check PendingAttestations - we can't be as agressive. + + var upgraded = false + val existingAttestations: MutableSet = timestamp.getAttestations() + + for (subStamp in timestamp.directlyVerified()) { + for (attestation in subStamp.attestations) { + if (attestation is PendingAttestation && !subStamp.isTimestampComplete) { + val calendarUrl = String(attestation.uri, StandardCharsets.UTF_8) + // var calendarUrl = calendarUrls[0]; + val commitment = subStamp.digest + + try { + val calendar = Calendar(calendarUrl) + val upgradedStamp = upgrade(subStamp, calendar, commitment, existingAttestations) + + try { + subStamp.merge(upgradedStamp) + } catch (e: Exception) { + e.printStackTrace() + } + + upgraded = true + } catch (e: Exception) { + Log.i("OpenTimestamps", e.message ?: "${e.javaClass.simpleName}") + } + } + } + } + + return upgraded + } + + @Throws(Exception::class) + private fun upgrade( + subStamp: Timestamp, + calendar: Calendar, + commitment: ByteArray, + existingAttestations: MutableSet, + ): Timestamp { + val upgradedStamp: Timestamp = + try { + calendar.getTimestamp(commitment) + } catch (e: Exception) { + Log.i("OpenTimestamps", "Calendar " + calendar.url + ": " + e.message) + throw e + } + + val attsFromRemote: MutableSet = upgradedStamp.getAttestations() + + if (attsFromRemote.isNotEmpty()) { + Log.i("OpenTimestamps", "Got 1 attestation(s) from " + calendar.url) + } + + // Set difference from remote attestations & existing attestations + val newAttestations = attsFromRemote.minus(existingAttestations) + + // changed & found_new_attestations + // foundNewAttestations = true; + // Log.i("OpenTimestamps", attsFromRemote.size + ' attestation(s) from ' + calendar.url); + + // Set union of existingAttestations & newAttestations + existingAttestations.addAll(newAttestations) + + return upgradedStamp + } +} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/README.md b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/README.md similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/README.md rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/README.md diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamDeserializationContext.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamDeserializationContext.kt new file mode 100644 index 000000000..35a56451d --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamDeserializationContext.kt @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots + +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException +import java.util.Arrays + +class StreamDeserializationContext( + var output: ByteArray, +) { + var counter: Int = 0 + + fun read(l: Int): ByteArray { + var l = l + if (this.counter == this.output.size) { + return byteArrayOf() + } + + if (l + this.counter > this.output.size) { + l = this.output.size - this.counter + } + + // const uint8Array = new Uint8Array(this.buffer,this.counter,l); + val uint8Array = Arrays.copyOfRange(this.output, this.counter, this.counter + l) + this.counter += l + + return uint8Array + } + + fun readBool(): Boolean { + val b = this.read(1)[0] + + if (b.toInt() == 0xff) { + return true + } else if (b.toInt() == 0x00) { + return false + } + + return false + } + + fun readVaruint(): Int { + var value = 0 + var shift: Byte = 0 + var b: Byte + + do { + b = this.read(1)[0] + value = value or ((b.toInt() and 127) shl shift.toInt()) + shift = (shift + 7).toByte() + } while ((b.toInt() and 128) != 0) + + return value + } + + @Throws(DeserializationException::class) + fun readBytes(expectedLength: Int): ByteArray { + if (expectedLength == 0) { + return this.readVarbytes(1024, 0) + } + + return this.read(expectedLength) + } + + @JvmOverloads + @Throws(DeserializationException::class) + fun readVarbytes( + maxLen: Int, + minLen: Int = 0, + ): ByteArray { + val l = this.readVaruint() + + if (l > maxLen) { + throw DeserializationException("varbytes max length exceeded;") + } else if (l < minLen) { + throw DeserializationException("varbytes min length not met;") + } + + return this.read(l) + } + + fun assertMagic(expectedMagic: ByteArray): Boolean { + val actualMagic = this.read(expectedMagic.size) + + return expectedMagic.contentEquals(actualMagic) + } + + fun assertEof(): Boolean { + val excess = this.read(1) + return excess.isNotEmpty() + } + + override fun toString(): String = this.output.contentToString() +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamSerializationContext.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamSerializationContext.kt new file mode 100644 index 000000000..f6e3daca0 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamSerializationContext.kt @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots + +class StreamSerializationContext { + val buffer: MutableList = ArrayList() + + val output: ByteArray + get() { + val bytes = ByteArray(this.buffer.size) + + for (i in this.buffer.indices) { + bytes[i] = this.buffer.get(i) + } + + return bytes + } + + fun writeBool(value: Boolean) { + if (value) { + this.writeByte(0xff.toByte()) + } else { + this.writeByte(0x00.toByte()) + } + } + + fun writeVaruint(value: Int) { + var value = value + if ((value) == 0) { + this.writeByte(0x00.toByte()) + } else { + while (value != 0) { + var b = ((value and 0xff) and 127).toByte() + + if ((value) > 127) { + b = (b.toInt() or 128).toByte() + } + + this.writeByte(b) + + if ((value) <= 127) { + break + } + + value = value shr 7 + } + } + } + + fun writeByte(value: Byte) { + this.buffer.add(value) + } + + fun writeBytes(value: ByteArray) { + for (b in value) { + this.writeByte(b) + } + } + + fun writeVarbytes(value: ByteArray) { + this.writeVaruint(value.size) + this.writeBytes(value) + } + + override fun toString(): String = this.output.contentToString() +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/Timestamp.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/Timestamp.kt new file mode 100644 index 000000000..dd72fc21d --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/Timestamp.kt @@ -0,0 +1,662 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots + +import com.vitorpamplona.quartz.nip01Core.core.toHexKey +import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils.arrayReverse +import com.vitorpamplona.quartz.nip03Timestamp.ots.attestation.BitcoinBlockHeaderAttestation +import com.vitorpamplona.quartz.nip03Timestamp.ots.attestation.TimeAttestation +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.Op +import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpBinary +import com.vitorpamplona.quartz.utils.Hex.encode +import java.util.Collections +import java.util.TreeMap + +/** + * Proof that one or more attestations commit to a message. + * The proof is in the form of a tree, with each node being a message, and the + * edges being operations acting on those messages. The leafs of the tree are + * attestations that attest to the time that messages in the tree existed prior. + */ +class Timestamp( + val digest: ByteArray, +) { + val attestations: MutableList = ArrayList() + val ops: HashMap = HashMap() + + /** + * Create a Serialize object. + * + * @return The byte array of the serialized timestamp + */ + fun serialize(): ByteArray { + val ctx = StreamSerializationContext() + serialize(ctx) + + return ctx.output + } + + /** + * Create a Serialize object. + * + * @param ctx - The stream serialization context. + */ + fun serialize(ctx: StreamSerializationContext) { + val sortedAttestations = this.attestations // TODO: Hm, this is just a reference copy... + Collections.sort(sortedAttestations) + + if (sortedAttestations.size > 1) { + for (i in 0..1 attestations : + // Search first BitcoinBlockHeaderAttestation + var minAttestation: TimeAttestation? = null + + for (entry in this.ops.entries) { + val timestamp: Timestamp = entry.value + + // Op op = entry.getKey(); + for (attestation in timestamp.getAttestations()) { + if (attestation is BitcoinBlockHeaderAttestation) { + if (minAttestation == null) { + minAttestation = attestation + } else { + if (minAttestation is BitcoinBlockHeaderAttestation && (minAttestation.height > attestation.height)) { + minAttestation = attestation + } + } + } + } + } + + // Only pending attestations : return the first + if (minAttestation == null) { + return allAttestations.values.iterator().next() + } + + // Remove attestation if not min attestation + var shrinked = false + + val it = this.ops.entries.iterator() + while (it.hasNext()) { + val entry = it.next() + val timestamp = entry.value + val op = entry.key + val attestations = timestamp.getAttestations() + + if (attestations.isNotEmpty() && attestations.contains(minAttestation) && !shrinked) { + timestamp.shrink() + shrinked = true + } else { + it.remove() + } + } + + return minAttestation + } + + /** + * Return as memory hierarchical object. + * + * @param indent - Initial hierarchical indention. + * @return The output string. + */ + fun toString(indent: Int): String { + val builder = StringBuilder() + builder.append(indention(indent) + "msg: " + encode(this.digest) + "\n") + builder.append(indention(indent) + this.attestations.size + " attestations: \n") + var i = 0 + + for (attestation in this.attestations) { + builder.append(indention(indent) + "[" + i + "] " + attestation.toString() + "\n") + i++ + } + + i = 0 + builder.append(indention(indent) + this.ops.size + " ops: \n") + + for (entry in this.ops.entries) { + val stamp: Timestamp = entry.value + val op: Op = entry.key + + builder.append(indention(indent) + "[" + i + "] op: " + op.toString() + "\n") + builder.append(indention(indent) + "[" + i + "] timestamp: \n") + builder.append(stamp.toString(indent + 1)) + i++ + } + + builder.append('\n') + + return builder.toString() + } + + private fun strResult( + verbosity: Boolean, + parameter: ByteArray?, + result: ByteArray?, + ): String { + var rr = "" + + if (verbosity == true && result != null) { + rr += " == " + val resultHex = result.toHexKey() + + if (parameter == null) { + rr += resultHex + } else { + val parameterHex = parameter.toHexKey() + + try { + val index = resultHex.indexOf(parameterHex) + val parameterHexHighlight = ANSI_BOLD + parameterHex + ANSI_ENDC + + if (index == 0) { + rr += parameterHexHighlight + + resultHex.substring( + index + parameterHex.length, + resultHex.length, + ) + } else { + rr += resultHex.substring(0, index) + parameterHexHighlight + } + } catch (err: Exception) { + rr += resultHex + } + } + } + + return rr + } + + /** + * Return as tree hierarchical object. + * + * @param indent - Initial hierarchical indention. + * @param verbosity - Verbose option. + * @return The output string. + */ + @JvmOverloads + fun strTree( + indent: Int, + verbosity: Boolean = false, + ): String { + val builder = StringBuilder() + + if (!this.attestations.isEmpty()) { + for (attestation in this.attestations) { + builder.append(indention(indent)) + builder.append( + "verify " + attestation.toString() + + strResult( + verbosity, + this.digest, + null, + ) + "\n", + ) + + if (attestation is BitcoinBlockHeaderAttestation) { + val tx = arrayReverse(this.digest).toHexKey() + builder.append(indention(indent) + "# Bitcoin block merkle root " + tx.lowercase() + "\n") + } + } + } + + if (this.ops.size > 1) { + val ordered = TreeMap(this.ops) + + for (entry in ordered.entries) { + val timestamp: Timestamp = entry.value!! + val op: Op = entry.key!! + + val curRes = op.call(this.digest) + var curPar: ByteArray? = null + + if (op is OpBinary) { + curPar = op.arg + } + + builder.append( + indention(indent) + " -> " + op.toString().lowercase() + + strResult( + verbosity, + curPar, + curRes, + ).lowercase() + "\n", + ) + builder.append(timestamp.strTree(indent + 1, verbosity)) + } + } else if (this.ops.size > 0) { + // output += com.eternitywall.ots.Timestamp.indention(indent); + for (entry in this.ops.entries) { + val timestamp: Timestamp = entry.value + val op: Op = entry.key + + val curRes = op.call(this.digest) + var curPar: ByteArray? = null + + if (op is OpBinary) { + curPar = op.arg + } + + builder.append( + indention(indent) + op.toString().lowercase() + + strResult( + verbosity, + curPar, + curRes, + ).lowercase() + "\n", + ) + builder.append(timestamp.strTree(indent, verbosity)) + } + } + + return builder.toString() + } + + /** + * Returns a list of all sub timestamps with attestations. + * + * @return List of all sub timestamps with attestations. + */ + fun directlyVerified(): MutableList { + if (!this.attestations.isEmpty()) { + val list: MutableList = ArrayList() + list.add(this) + return list + } + + val list: MutableList = ArrayList() + + for (entry in this.ops.entries) { + val ts: Timestamp = entry.value + + // Op op = entry.getKey(); + val result = ts.directlyVerified() + list.addAll(result) + } + + return list + } + + /** + * Returns a set of all Attestations. + * + * @return Set of all timestamp attestations. + */ + fun getAttestations(): MutableSet { + val set: MutableSet = HashSet() + + for (item in this.allAttestations().entries) { + // byte[] msg = item.getKey(); + val attestation = item.value + set.add(attestation) + } + + return set + } + + val isTimestampComplete: Boolean + /** + * Determine if timestamp is complete and can be verified. + * + * @return True if the timestamp is complete, False otherwise. + */ + get() { + for (item in this.allAttestations().entries) { + // byte[] msg = item.getKey(); + val attestation = item.value + + if (attestation is BitcoinBlockHeaderAttestation) { + return true + } + } + + return false + } + + /** + * Iterate over all attestations recursively + * + * @return Returns iterable of (msg, attestation) + */ + fun allAttestations(): HashMap { + val map = HashMap() + + for (attestation in this.attestations) { + map.put(this.digest, attestation) + } + + for (entry in this.ops.entries) { + val ts: Timestamp = entry.value + + // Op op = entry.getKey(); + val subMap = ts.allAttestations() + + for (item in subMap.entries) { + val msg = item.key + val attestation = item.value + map.put(msg, attestation) + } + } + + return map + } + + /** + * Iterate over all tips recursively + * + * @return Returns iterable of (msg, attestation) + */ + fun allTips(): MutableSet { + val set: MutableSet = HashSet() + + if (this.ops.size == 0) { + set.add(this.digest) + } + + for (entry in this.ops.entries) { + val ts: Timestamp = entry.value!! + + // Op op = entry.getKey(); + val subSet = ts.allTips() + + for (msg in subSet) { + set.add(msg) + } + } + + return set + } + + /** + * Compare timestamps. + * + * @param timestamp the timestamp to compare with + * @return Returns true if timestamps are equals + */ + fun equals(timestamp: Timestamp): Boolean { + if (this.digest.contentEquals(timestamp.digest) == false) { + return false + } + + // Check attestations + if (this.attestations.size != timestamp.attestations.size) { + return false + } + + for (i in this.attestations.indices) { + val ta1 = this.attestations.get(i) + val ta2 = timestamp.attestations.get(i) + + if (!(ta1 == ta2)) { + return false + } + } + + // Check operations + if (this.ops.size != timestamp.ops.size) { + return false + } + + // Order list of operations + val list1 = sortToList(this.ops.entries) + val list2 = sortToList(timestamp.ops.entries) + + for (i in list1.indices) { + val op1 = list1.get(i).key + val op2: Op? = list2.get(i).key + + if (op1 != op2) { + return false + } + + val t1 = list1.get(i).value + val t2 = list2.get(i).value + + if (!t1.equals(t2)) { + return false + } + } + + return true + } + + /** + * Add Op to current timestamp and return the sub stamp + * + * @param op - The operation to insert + * @return Returns the sub timestamp + */ + fun add(op: Op): Timestamp { + // nonce_appended_stamp = timestamp.ops.add(com.vitorpamplona.quartz.ots.op.OpAppend(os.urandom(16))) + // Op opAppend = new OpAppend(bytes); + + val existing = this.ops.get(op) + + if (existing != null) { + return existing + } + + val stamp = Timestamp(op.call(this.digest)) + this.ops.put(op, stamp) + + return stamp + } + + /** + * Retrieve a sorted list of all map entries. + * + * @param setEntries - The entries set of ops hashmap + * @return Returns the sorted list of map entries + */ + fun sortToList(setEntries: MutableSet>): MutableList> { + val entries: MutableList> = ArrayList(setEntries) + Collections.sort( + entries, + Comparator> { a, b -> a.key.compareTo(b.key) }, + ) + + return entries + } + + companion object { + val ANSI_HEADER = "\u001B[95m" + val ANSI_OKBLUE = "\u001B[94m" + val ANSI_OKGREEN = "\u001B[92m" + val ANSI_WARNING = "\u001B[93m" + val ANSI_FAIL = "\u001B[91m" + val ANSI_ENDC = "\u001B[0m" + val ANSI_BOLD = "\u001B[1m" + val ANSI_UNDERLINE = "\u001B[4m" + + /** + * Deserialize a Timestamp. + * + * @param ots - The serialized byte array. + * @param initialMsg - The initial message. + * @return The deserialized Timestamp. + */ + @Throws(DeserializationException::class) + fun deserialize( + ots: ByteArray, + initialMsg: ByteArray, + ): Timestamp { + val ctx = StreamDeserializationContext(ots) + + return deserialize(ctx, initialMsg) + } + + /** + * Deserialize a Timestamp. + * Because the serialization format doesn't include the message that the + * timestamp operates on, you have to provide it so that the correct + * operation results can be calculated. + * The message you provide is assumed to be correct; if it causes a op to + * raise MsgValueError when the results are being calculated (done + * immediately, not lazily) DeserializationError is raised instead. + * + * @param ctx - The stream deserialization context. + * @param initialMsg - The initial message. + * @return The deserialized Timestamp. + */ + @JvmStatic + @Throws(DeserializationException::class) + fun deserialize( + ctx: StreamDeserializationContext, + initialMsg: ByteArray, + ): Timestamp { + val self = Timestamp(initialMsg) + var tag = ctx.readBytes(1)[0] + + while ((tag.toInt() and 0xff) == 0xff) { + val current = ctx.readBytes(1)[0] + doTagOrAttestation(self, ctx, current, initialMsg) + tag = ctx.readBytes(1)[0] + } + + doTagOrAttestation(self, ctx, tag, initialMsg) + + return self + } + + @Throws(DeserializationException::class) + private fun doTagOrAttestation( + self: Timestamp, + ctx: StreamDeserializationContext, + tag: Byte, + initialMsg: ByteArray, + ) { + if ((tag.toInt() and 0xff) == 0x00) { + val attestation = TimeAttestation.deserialize(ctx) + self.attestations.add(attestation) + } else { + val op = Op.deserializeFromTag(ctx, tag) + val result = op!!.call(initialMsg) + + val stamp: Timestamp = deserialize(ctx, result) + self.ops.put(op, stamp) + } + } + + /** + * Indention function for printing tree. + * + * @param pos - Initial hierarchical indention. + * @return The output space string. + */ + fun indention(pos: Int): String { + val builder = StringBuilder() + + for (i in 0.. This describes my type parameter + * @return the first value that is not null. If all objects are null, then it returns null. + */ + @Deprecated("Not used by Java OpenTimestamps itself, and doesn't offer much useful functionality.") + fun coalesce(vararg items: T?): T? { + for (i in items) { + if (i != null) { + return i + } + } + + return null + } + + /** + * Returns a copy of the byte array argument, or null if the byte array argument is null. + * + * @param data the array of bytes to copy + * @return the copied byte array + */ + @JvmStatic + fun arraysCopy(data: ByteArray): ByteArray { + val copy = ByteArray(data.size) + System.arraycopy(data, 0, copy, 0, data.size) + + return copy + } + + /** + * Returns a byte array which is the result of concatenating the two passed in byte arrays. + * None of the passed in arrays may be null. + * + * @param array1 the first array of bytes + * @param array2 the second array of bytes + * @return a copy of array1 and array2 concatenated together + */ + @JvmStatic + fun arraysConcat( + array1: ByteArray, + array2: ByteArray, + ): ByteArray { + val array1and2 = ByteArray(array1.size + array2.size) + System.arraycopy(array1, 0, array1and2, 0, array1.size) + System.arraycopy(array2, 0, array1and2, array1.size, array2.size) + + return array1and2 + } + + /** + * Returns a given length array of random bytes. + * + * @param length the requested length of the byte array + * @return a given length array of random bytes + * @throws NoSuchAlgorithmException for Java 8 implementations + */ + @JvmStatic + @Throws(NoSuchAlgorithmException::class) + fun randBytes(length: Int): ByteArray { + // Java 6 & 7: + val random = SecureRandom() + val bytes = ByteArray(length) + random.nextBytes(bytes) + + // Java 8 (even more secure): + // SecureRandom.getInstanceStrong().nextBytes(bytes); + return bytes + } + + /** + * Returns a reversed copy of the passed in byte array. + * + * @param array the byte array to reverse + * @return a copy of the byte array, reversed + */ + @JvmStatic + fun arrayReverse(array: ByteArray): ByteArray { + val reversedArray = ByteArray(array.size) + + var i = array.size - 1 + var j = 0 + while (i >= 0) { + reversedArray[j] = array[i] + i-- + j++ + } + + return reversedArray + } + + /** + * Compares two byte arrays. + * + * @param left the left byte array to compare with + * @param right the right byte array to compare with + * @return 0 if the arrays are identical, negative if left < right, positive if left > right + */ + @JvmStatic + fun compare( + left: ByteArray, + right: ByteArray, + ): Int { + var i = 0 + var j = 0 + while (i < left.size && j < right.size) { + val a = (left[i].toInt() and 0xff) + val b = (right[j].toInt() and 0xff) + + if (a != b) { + return a - b + } + i++ + j++ + } + + return left.size - right.size + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/VerifyResult.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/VerifyResult.kt new file mode 100644 index 000000000..bdd5cb1a3 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/VerifyResult.kt @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots + +import android.annotation.SuppressLint +import java.text.DateFormatSymbols +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + +/** + * Class that lets us compare, sort, store and print timestamps. + */ +class VerifyResult( + val timestamp: Long?, + val height: Int, +) : Comparable { + enum class Chains { BITCOIN } + + /** + * Returns, if existing, a string representation describing the existence of a block attest + */ + override fun toString(): String { + if (height == 0 || timestamp == null) { + return "" + } + + val pattern = "yyyy-MM-dd z" + val locale = Locale("en", "UK") + val dateFormatSymbols = DateFormatSymbols(locale) + + @SuppressLint("SimpleDateFormat") + val simpleDateFormat = + SimpleDateFormat(pattern, dateFormatSymbols) + val string = simpleDateFormat.format(Date(timestamp!! * 1000)) + + return "block $height attests data existed as of $string" + } + + override fun compareTo(other: VerifyResult): Int = this.height - other.height + + override fun equals(other: Any?): Boolean { + val vr = other as VerifyResult + return this.timestamp == vr.timestamp && this.height == vr.height + } + + override fun hashCode(): Int = (((this.timestamp) as Long).toInt()) xor this.height +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/BitcoinBlockHeaderAttestation.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/BitcoinBlockHeaderAttestation.kt new file mode 100644 index 000000000..354418cd9 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/BitcoinBlockHeaderAttestation.kt @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.attestation + +import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray +import com.vitorpamplona.quartz.nip01Core.core.toHexKey +import com.vitorpamplona.quartz.nip03Timestamp.ots.BlockHeader +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamSerializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.VerificationException + +/** + * Bitcoin Block Header Attestation. + * The commitment digest will be the merkleroot of the blockheader. + * The block height is recorded so that looking up the correct block header in + * an external block header database doesn't require every header to be stored + * locally (33MB and counting). (remember that a memory-constrained local + * client can save an MMR that commits to all blocks, and use an external service to fill + * in pruned details). + * Otherwise no additional redundant data about the block header is recorded. + * This is very intentional: since the attestation contains (nearly) the + * absolute bare minimum amount of data, we encourage implementations to do + * the correct thing and get the block header from a by-height index, check + * that the merkleroots match, and then calculate the time from the header + * information. Providing more data would encourage implementations to cheat. + * Remember that the only thing that would invalidate the block height is a + * reorg, but in the event of a reorg the merkleroot will be invalid anyway, + * so there's no point to recording data in the attestation like the header + * itself. At best that would just give us extra confirmation that a reorg + * made the attestation invalid; reorgs deep enough to invalidate timestamps are + * exceptionally rare events anyway, so better to just tell the user the timestamp + * can't be verified rather than add almost-never tested code to handle that case + * more gracefully. + * + * @see TimeAttestation + */ +class BitcoinBlockHeaderAttestation( + val height: Int, +) : TimeAttestation() { + override fun tag(): ByteArray = TAG + + override fun serializePayload(ctx: StreamSerializationContext) { + ctx.writeVaruint(this.height) + } + + override fun toString(): String = "BitcoinBlockHeaderAttestation(" + this.height + ")" + + override fun compareTo(other: TimeAttestation): Int { + val ob = other as BitcoinBlockHeaderAttestation + + return this.height - ob.height + } + + override fun equals(other: Any?): Boolean { + if (other !is BitcoinBlockHeaderAttestation) { + return false + } + + if (!this.tag().contentEquals(other.tag())) { + return false + } + + if (this.height != other.height) { + return false + } + + return true + } + + override fun hashCode(): Int = this.tag().contentHashCode() xor this.height + + /** + * Verify attestation against a Bitcoin block header. + * @param digest the digest + * @param block the Bitcoin block header + * @return the block time on success; raises VerificationError on failure. + * @throws VerificationException verification exception + */ + @Throws(VerificationException::class) + fun verifyAgainstBlockheader( + digest: ByteArray, + block: BlockHeader, + ): Long? { + if (digest.size != 32) { + throw VerificationException("Expected digest with length 32 bytes; got " + digest.size + " bytes") + } else if (!digest.contentEquals(block.merkleRoot.hexToByteArray())) { + throw VerificationException("Digest ${digest.toHexKey()} does not match merkleroot ${block.merkleRoot}") + } + + return block.getTime() + } + + companion object { + val TAG: ByteArray = + byteArrayOf( + 0x05.toByte(), + 0x88.toByte(), + 0x96.toByte(), + 0x0d.toByte(), + 0x73.toByte(), + 0xd7.toByte(), + 0x19.toByte(), + 0x01.toByte(), + ) + + val chain: String = "bitcoin" + + fun deserialize(ctxPayload: StreamDeserializationContext): BitcoinBlockHeaderAttestation = BitcoinBlockHeaderAttestation(ctxPayload.readVaruint()) + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/PendingAttestation.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/PendingAttestation.kt new file mode 100644 index 000000000..0644380fd --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/PendingAttestation.kt @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.attestation + +import android.util.Log +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamSerializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils.compare +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException +import java.nio.charset.StandardCharsets + +/** + * Pending attestations. + * Commitment has been recorded in a remote calendar for future attestation, + * and we have a URI to find a more complete timestamp in the future. + * Nothing other than the URI is recorded, nor is there provision made to add + * extra metadata (other than the URI) in future upgrades. The rational here + * is that remote calendars promise to keep commitments indefinitely, so from + * the moment they are created it should be possible to find the commitment in + * the calendar. Thus if you're not satisfied with the local verifiability of + * a timestamp, the correct thing to do is just ask the remote calendar if + * additional attestations are available and/or when they'll be available. + * While we could additional metadata like what types of attestations the + * remote calendar expects to be able to provide in the future, that metadata + * can easily change in the future too. Given that we don't expect timestamps + * to normally have more than a small number of remote calendar attestations, + * it'd be better to have verifiers get the most recent status of such + * information (possibly with appropriate negative response caching). + * + * @see TimeAttestation + */ +class PendingAttestation( + val uri: ByteArray, +) : TimeAttestation() { + override fun tag(): ByteArray = TAG + + override fun serializePayload(ctx: StreamSerializationContext) { + ctx.writeVarbytes(this.uri) + } + + override fun toString(): String = "PendingAttestation(\'" + String(this.uri, StandardCharsets.UTF_8) + "\')" + + override fun compareTo(other: TimeAttestation): Int { + val opa = other as PendingAttestation + + return compare(this.uri, opa.uri) + } + + override fun equals(other: Any?): Boolean { + if (other !is PendingAttestation) { + return false + } + + if (!this.tag().contentEquals(other.tag())) { + return false + } + + if (!this.uri.contentEquals(other.uri)) { + return false + } + + return true + } + + override fun hashCode(): Int = this.tag().contentHashCode() xor this.uri.contentHashCode() + + companion object { + val TAG: ByteArray = + byteArrayOf( + 0x83.toByte(), + 0xdf.toByte(), + 0xe3.toByte(), + 0x0d.toByte(), + 0x2e.toByte(), + 0xf9.toByte(), + 0x0c.toByte(), + 0x8e.toByte(), + ) + + const val MAX_URI_LENGTH: Int = 1000 + + const val ALLOWED_URI_CHARS: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._/:" + + fun checkUri(uri: ByteArray): Boolean { + if (uri.size > MAX_URI_LENGTH) { + System.err.print("URI exceeds maximum length") + + return false + } + + for (i in uri.indices) { + val c = String.format("%c", uri[i])[0] + + if (ALLOWED_URI_CHARS.indexOf(c) < 0) { + Log.e("OpenTimestamp", "URI contains invalid character ") + + return false + } + } + + return true + } + + @JvmStatic + @Throws(DeserializationException::class) + fun deserialize(ctxPayload: StreamDeserializationContext): PendingAttestation { + val utf8Uri: ByteArray + try { + utf8Uri = ctxPayload.readVarbytes(MAX_URI_LENGTH) + } catch (_: DeserializationException) { + Log.e("OpenTimestamp", "URI too long and thus invalid: ") + throw DeserializationException("Invalid URI: ") + } + + if (!checkUri(utf8Uri)) { + Log.e("OpenTimestamp", "Invalid URI: ") + throw DeserializationException("Invalid URI: ") + } + + return PendingAttestation(utf8Uri) + } + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/TimeAttestation.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/TimeAttestation.kt new file mode 100644 index 000000000..f3a40286f --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/TimeAttestation.kt @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.attestation + +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamSerializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException + +/** + * Class representing Timestamp signature verification + */ +abstract class TimeAttestation : Comparable { + open fun tag(): ByteArray = byteArrayOf() + + /** + * Serialize a a general Time Attestation to the specific subclass Attestation. + * + * @param ctx The output stream serialization context. + */ + fun serialize(ctx: StreamSerializationContext) { + ctx.writeBytes(this.tag()) + val ctxPayload = StreamSerializationContext() + serializePayload(ctxPayload) + ctx.writeVarbytes(ctxPayload.output) + } + + open fun serializePayload(ctx: StreamSerializationContext) { + // TODO: Is this intentional? + } + + override fun compareTo(other: TimeAttestation): Int { + val deltaTag = Utils.compare(this.tag(), other.tag()) + + return if (deltaTag == 0) { + this.compareTo(other) + } else { + deltaTag + } + } + + companion object { + const val TAG_SIZE: Int = 8 + + const val MAX_PAYLOAD_SIZE: Int = 8192 + + /** + * Deserialize a general Time Attestation to the specific subclass Attestation. + * + * @param ctx The stream deserialization context. + * @return The specific subclass Attestation. + */ + @Throws(DeserializationException::class) + fun deserialize(ctx: StreamDeserializationContext): TimeAttestation { + // console.log('attestation deserialize'); + + val tag = ctx.readBytes(TAG_SIZE) + + // console.log('tag: ', com.vitorpamplona.quartz.ots.Utils.bytesToHex(tag)); + val serializedAttestation = ctx.readVarbytes(MAX_PAYLOAD_SIZE) + + // console.log('serializedAttestation: ', com.vitorpamplona.quartz.ots.Utils.bytesToHex(serializedAttestation)); + val ctxPayload = StreamDeserializationContext(serializedAttestation) + + // eslint no-use-before-define: ["error", { "classes": false }] + if (tag.contentEquals(PendingAttestation.TAG)) { + return PendingAttestation.deserialize(ctxPayload) + } else if (tag.contentEquals(BitcoinBlockHeaderAttestation.TAG)) { + return BitcoinBlockHeaderAttestation.deserialize(ctxPayload) + } + + return UnknownAttestation(tag, serializedAttestation) + } + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/UnknownAttestation.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/UnknownAttestation.kt new file mode 100644 index 000000000..a128070d2 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/UnknownAttestation.kt @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.attestation + +import com.vitorpamplona.quartz.nip01Core.core.toHexKey +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamSerializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException + +/** + * Placeholder for attestations that don't support + * + * @see TimeAttestation + */ +class UnknownAttestation internal constructor( + val tag: ByteArray, + val payload: ByteArray, +) : TimeAttestation() { + override fun tag(): ByteArray = tag + + override fun serializePayload(ctx: StreamSerializationContext) { + ctx.writeBytes(this.payload) + } + + override fun toString(): String = "UnknownAttestation " + this.tag().toHexKey() + ' ' + this.payload.toHexKey() + + override fun compareTo(other: TimeAttestation): Int { + val ota = other as UnknownAttestation + + return Utils.compare(this.payload, ota.payload) + } + + override fun equals(other: Any?): Boolean { + if (other !is UnknownAttestation) { + return false + } + + if (!this.tag().contentEquals(other.tag())) { + return false + } + + if (!this.payload.contentEquals(other.payload)) { + return false + } + + return true + } + + override fun hashCode(): Int = this.tag().contentHashCode() xor this.payload.contentHashCode() + + companion object { + val TAG: ByteArray = byteArrayOf() + + @Throws(DeserializationException::class) + fun deserialize( + ctxPayload: StreamDeserializationContext, + tag: ByteArray, + ): UnknownAttestation { + val payload = ctxPayload.readVarbytes(MAX_PAYLOAD_SIZE) + return UnknownAttestation(tag, payload) + } + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Digest.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Digest.kt new file mode 100644 index 000000000..59536c1da --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Digest.kt @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.crypto + +/** + * Message digest interface + */ +interface Digest { + /** + * Return the algorithm name + * + * @return the algorithm name + */ + fun getAlgorithmName(): String + + /** + * Return the size, in bytes, of the digest produced by this message digest. + * + * @return the size, in bytes, of the digest produced by this message digest. + */ + fun getDigestSize(): Int + + /** + * Update the message digest with a single byte. + * + * @param in the input byte to be entered. + */ + fun update(`in`: Byte) + + /** + * Update the message digest with a block of bytes. + * + * @param in the byte array containing the data. + * @param inOff the offset into the byte array where the data starts. + * @param len the length of the data. + */ + fun update( + `in`: ByteArray, + inOff: Int, + len: Int, + ) + + /** + * Close the digest, producing the final digest value. The doFinal + * call also resets the digest. + * + * @param out the array the digest is to be copied into. + * @param outOff the offset into the out array the digest is to start at. + * @return something + * @see .reset + */ + fun doFinal( + out: ByteArray, + outOff: Int, + ): Int + + /** + * Reset the digest back to it's initial state. + */ + fun reset() +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/ExtendedDigest.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/ExtendedDigest.kt new file mode 100644 index 000000000..74b030980 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/ExtendedDigest.kt @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.crypto + +interface ExtendedDigest : Digest { + /** + * Return the size in bytes of the internal buffer the digest applies it's compression + * function to. + * + * @return byte length of the digests internal buffer. + */ + fun getByteLength(): Int +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/GeneralDigest.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/GeneralDigest.kt new file mode 100644 index 000000000..4f52a3434 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/GeneralDigest.kt @@ -0,0 +1,174 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.crypto + +import com.vitorpamplona.quartz.nip03Timestamp.ots.crypto.Pack.bigEndianToInt +import com.vitorpamplona.quartz.nip03Timestamp.ots.crypto.Pack.bigEndianToLong +import com.vitorpamplona.quartz.nip03Timestamp.ots.crypto.Pack.intToBigEndian +import com.vitorpamplona.quartz.nip03Timestamp.ots.crypto.Pack.longToBigEndian +import kotlin.math.max + +/** + * Base implementation of MD4 family style digest as outlined in + * "Handbook of Applied Cryptography", pages 344 - 347. + */ +abstract class GeneralDigest : + ExtendedDigest, + Memoable { + private val xBuf = ByteArray(4) + private var xBufOff = 0 + + private var byteCount: Long = 0 + + /** + * Standard constructor + */ + protected constructor() { + xBufOff = 0 + } + + /** + * Copy constructor. We are using copy constructors in place + * of the Object.clone() interface as this interface is not + * supported by J2ME. + * + * @param t the GeneralDigest + */ + protected constructor(t: GeneralDigest) { + copyIn(t) + } + + protected constructor(encodedState: ByteArray) { + System.arraycopy(encodedState, 0, xBuf, 0, xBuf.size) + xBufOff = bigEndianToInt(encodedState, 4) + byteCount = bigEndianToLong(encodedState, 8) + } + + protected fun copyIn(t: GeneralDigest) { + System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.size) + + xBufOff = t.xBufOff + byteCount = t.byteCount + } + + override fun update(`in`: Byte) { + xBuf[xBufOff++] = `in` + + if (xBufOff == xBuf.size) { + processWord(xBuf, 0) + xBufOff = 0 + } + + byteCount++ + } + + override fun update( + `in`: ByteArray, + inOff: Int, + len: Int, + ) { + var len = len + len = max(0, len) + + // + // fill the current word + // + var i = 0 + + if (xBufOff != 0) { + while (i < len) { + xBuf[xBufOff++] = `in`[inOff + i++] + + if (xBufOff == 4) { + processWord(xBuf, 0) + xBufOff = 0 + break + } + } + } + + // + // process whole words. + // + val limit = ((len - i) and 3.inv()) + i + + while (i < limit) { + processWord(`in`, inOff + i) + i += 4 + } + + // + // load in the remainder. + // + while (i < len) { + xBuf[xBufOff++] = `in`[inOff + i++] + } + + byteCount += len.toLong() + } + + fun finish() { + val bitLength = (byteCount shl 3) + + // + // add the pad bytes. + // + update(128.toByte()) + + while (xBufOff != 0) { + update(0.toByte()) + } + + processLength(bitLength) + processBlock() + } + + override fun reset() { + byteCount = 0 + + xBufOff = 0 + + for (i in xBuf.indices) { + xBuf[i] = 0 + } + } + + protected fun populateState(state: ByteArray) { + System.arraycopy(xBuf, 0, state, 0, xBufOff) + intToBigEndian(xBufOff, state, 4) + longToBigEndian(byteCount, state, 8) + } + + override fun getByteLength(): Int = BYTE_LENGTH + + protected abstract fun processWord( + `in`: ByteArray, + inOff: Int, + ) + + protected abstract fun processLength(bitLength: Long) + + protected abstract fun processBlock() + + companion object { + private const val BYTE_LENGTH = 64 + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/KeccakDigest.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/KeccakDigest.kt new file mode 100644 index 000000000..99b52fdc5 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/KeccakDigest.kt @@ -0,0 +1,551 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.crypto + +import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils.arrayFill +import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils.arraysCopy + +/** + * Implementation of Keccak based on following KeccakNISTInterface.c from http://keccak.noekeon.org/ + * + * + * Following the naming conventions used in the C source code to enable easy review of the implementation. + */ +class KeccakDigest : ExtendedDigest { + var state: ByteArray = ByteArray((1600 / 8)) + var dataQueue: ByteArray = ByteArray((1536 / 8)) + var rate: Int = 0 + var bitsInQueue: Int = 0 + var fixedOutputLength: Int = 0 + var squeezing: Boolean = false + var bitsAvailableForSqueezing: Int = 0 + var chunk: ByteArray = byteArrayOf() + var oneByte: ByteArray = byteArrayOf() + + private fun clearDataQueueSection( + off: Int, + len: Int, + ) { + for (i in off.. 0) { + oneByte[0] = partialByte + absorb(oneByte, 0, partialBits.toLong()) + } + + squeeze(out, outOff, fixedOutputLength.toLong()) + reset() + + return getDigestSize() + } + + override fun reset() { + init(fixedOutputLength) + } + + /** + * Return the size of block that the compression function is applied to in bytes. + * + * @return internal byte length of a block. + */ + override fun getByteLength(): Int = rate / 8 + + private fun init(bitLength: Int) { + when (bitLength) { + 288 -> initSponge(1024, 576) + 128 -> initSponge(1344, 256) + 224 -> initSponge(1152, 448) + 256 -> initSponge(1088, 512) + 384 -> initSponge(832, 768) + 512 -> initSponge(576, 1024) + else -> throw IllegalArgumentException("bitLength must be one of 128, 224, 256, 288, 384, or 512.") + } + } + + private fun initSponge( + rate: Int, + capacity: Int, + ) { + check(rate + capacity == 1600) { "rate + capacity != 1600" } + + check(!((rate <= 0) || (rate >= 1600) || ((rate % 64) != 0))) { "invalid rate value" } + + this.rate = rate + // this is never read, need to check to see why we want to save it + // this.capacity = capacity; + arrayFill(this.state, 0.toByte()) + arrayFill(this.dataQueue, 0.toByte()) + this.bitsInQueue = 0 + this.squeezing = false + this.bitsAvailableForSqueezing = 0 + this.fixedOutputLength = capacity / 2 + this.chunk = ByteArray(rate / 8) + this.oneByte = ByteArray(1) + } + + private fun absorbQueue() { + keccakAbsorb(state, dataQueue, rate / 8) + bitsInQueue = 0 + } + + fun absorb( + data: ByteArray, + off: Int, + databitlen: Long, + ) { + var i: Long + var j: Long + var wholeBlocks: Long + + check((bitsInQueue % 8) == 0) { "attempt to absorb with odd length queue" } + + check(!squeezing) { "attempt to absorb while squeezing" } + + i = 0 + + while (i < databitlen) { + if ((bitsInQueue == 0) && (databitlen >= rate) && (i <= (databitlen - rate))) { + wholeBlocks = (databitlen - i) / rate + + j = 0 + while (j < wholeBlocks) { + System.arraycopy( + data, + (off + (i / 8) + (j * chunk.size)).toInt(), + chunk, + 0, + chunk.size, + ) + + // displayIntermediateValues.displayBytes(1, "Block to be absorbed", curData, rate / 8); + keccakAbsorb(state, chunk, chunk.size) + j++ + } + + i += wholeBlocks * rate + } else { + var partialBlock = (databitlen - i).toInt() + + if (partialBlock + bitsInQueue > rate) { + partialBlock = rate - bitsInQueue + } + + val partialByte = partialBlock % 8 + partialBlock -= partialByte + System.arraycopy( + data, + off + (i / 8).toInt(), + dataQueue, + bitsInQueue / 8, + partialBlock / 8, + ) + + bitsInQueue += partialBlock + i += partialBlock.toLong() + + if (bitsInQueue == rate) { + absorbQueue() + } + + if (partialByte > 0) { + val mask = (1 shl partialByte) - 1 + dataQueue[bitsInQueue / 8] = + (data[off + ((i / 8).toInt())].toInt() and mask).toByte() + bitsInQueue += partialByte + i += partialByte.toLong() + } + } + } + } + + private fun padAndSwitchToSqueezingPhase() { + if (bitsInQueue + 1 == rate) { + dataQueue[bitsInQueue / 8] = + (dataQueue[bitsInQueue / 8].toInt() or (1 shl (bitsInQueue % 8))).toByte() + absorbQueue() + clearDataQueueSection(0, rate / 8) + } else { + clearDataQueueSection((bitsInQueue + 7) / 8, rate / 8 - (bitsInQueue + 7) / 8) + dataQueue[bitsInQueue / 8] = + (dataQueue[bitsInQueue / 8].toInt() or (1 shl (bitsInQueue % 8))).toByte() + } + + dataQueue[(rate - 1) / 8] = (dataQueue[(rate - 1) / 8].toInt() or (1 shl ((rate - 1) % 8))).toByte() + absorbQueue() + + // displayIntermediateValues.displayText(1, "--- Switching to squeezing phase ---"); + if (rate == 1024) { + keccakExtract1024bits(state, dataQueue) + bitsAvailableForSqueezing = 1024 + } else { + keccakExtract(state, dataQueue, rate / 64) + bitsAvailableForSqueezing = rate + } + + // displayIntermediateValues.displayBytes(1, "Block available for squeezing", dataQueue, bitsAvailableForSqueezing / 8); + squeezing = true + } + + fun squeeze( + output: ByteArray, + offset: Int, + outputLength: Long, + ) { + var i: Long + var partialBlock: Int + + if (!squeezing) { + padAndSwitchToSqueezingPhase() + } + + check((outputLength % 8) == 0L) { "outputLength not a multiple of 8" } + + i = 0 + + while (i < outputLength) { + if (bitsAvailableForSqueezing == 0) { + keccakPermutation(state) + + if (rate == 1024) { + keccakExtract1024bits(state, dataQueue) + bitsAvailableForSqueezing = 1024 + } else { + keccakExtract(state, dataQueue, rate / 64) + bitsAvailableForSqueezing = rate + } + + // displayIntermediateValues.displayBytes(1, "Block available for squeezing", dataQueue, bitsAvailableForSqueezing / 8); + } + + partialBlock = bitsAvailableForSqueezing + + if (partialBlock.toLong() > outputLength - i) { + partialBlock = (outputLength - i).toInt() + } + + System.arraycopy( + dataQueue, + (rate - bitsAvailableForSqueezing) / 8, + output, + offset + (i / 8).toInt(), + partialBlock / 8, + ) + bitsAvailableForSqueezing -= partialBlock + i += partialBlock.toLong() + } + } + + private fun fromBytesToWords( + stateAsWords: LongArray, + state: ByteArray, + ) { + for (i in 0..<(1600 / 64)) { + stateAsWords[i] = 0 + val index = i * (64 / 8) + + for (j in 0..<(64 / 8)) { + stateAsWords[i] = + stateAsWords[i] or ((state[index + j].toLong() and 0xffL) shl ((8 * j))) + } + } + } + + private fun fromWordsToBytes( + state: ByteArray, + stateAsWords: LongArray, + ) { + for (i in 0..<(1600 / 64)) { + val index = i * (64 / 8) + + for (j in 0..<(64 / 8)) { + state[index + j] = ((stateAsWords[i] ushr ((8 * j))) and 0xFFL).toByte() + } + } + } + + private fun keccakPermutation(state: ByteArray) { + val longState = LongArray(state.size / 8) + + fromBytesToWords(longState, state) + + // displayIntermediateValues.displayStateAsBytes(1, "Input of permutation", longState); + keccakPermutationOnWords(longState) + + // displayIntermediateValues.displayStateAsBytes(1, "State after permutation", longState); + fromWordsToBytes(state, longState) + } + + private fun keccakPermutationAfterXor( + state: ByteArray, + data: ByteArray, + dataLengthInBytes: Int, + ) { + var i: Int + + i = 0 + while (i < dataLengthInBytes) { + state[i] = (state[i].toInt() xor data[i].toInt()).toByte() + i++ + } + + keccakPermutation(state) + } + + private fun keccakPermutationOnWords(state: LongArray) { + var i: Int + + // displayIntermediateValues.displayStateAs64bitWords(3, "Same, with lanes as 64-bit words", state); + i = 0 + while (i < 24) { + // displayIntermediateValues.displayRoundNumber(3, i); + theta(state) + + // displayIntermediateValues.displayStateAs64bitWords(3, "After theta", state); + rho(state) + + // displayIntermediateValues.displayStateAs64bitWords(3, "After rho", state); + pi(state) + + // displayIntermediateValues.displayStateAs64bitWords(3, "After pi", state); + chi(state) + + // displayIntermediateValues.displayStateAs64bitWords(3, "After chi", state); + iota(state, i) + i++ + } + } + + var cArray: LongArray = LongArray(5) + + private fun theta(array: LongArray) { + for (x in 0..4) { + cArray[x] = 0 + + for (y in 0..4) { + cArray[x] = cArray[x] xor array[x + 5 * y] + } + } + for (x in 0..4) { + val dX = + ((((cArray[(x + 1) % 5]) shl 1) xor ((cArray[(x + 1) % 5]) ushr (64 - 1)))) xor cArray[(x + 4) % 5] + + for (y in 0..4) { + array[x + 5 * y] = array[x + 5 * y] xor dX + } + } + } + + private fun rho(array: LongArray) { + for (x in 0..4) { + for (y in 0..4) { + val index = x + 5 * y + array[index] = + (if (KeccakRhoOffsets[index] != 0) (((array[index]) shl KeccakRhoOffsets[index]) xor ((array[index]) ushr (64 - KeccakRhoOffsets[index]))) else array[index]) + } + } + } + + var tempA: LongArray = LongArray(25) + + private fun pi(array: LongArray) { + System.arraycopy(array, 0, tempA, 0, tempA.size) + + for (x in 0..4) { + for (y in 0..4) { + array[y + 5 * ((2 * x + 3 * y) % 5)] = tempA[x + 5 * y] + } + } + } + + var chiC: LongArray = LongArray(5) + + private fun chi(array: LongArray) { + for (y in 0..4) { + for (x in 0..4) { + chiC[x] = + array[x + 5 * y] xor ((array[(((x + 1) % 5) + 5 * y)].inv()) and array[(((x + 2) % 5) + 5 * y)]) + } + + for (x in 0..4) { + array[x + 5 * y] = chiC[x] + } + } + } + + private fun iota( + array: LongArray, + indexRound: Int, + ) { + array[(((0) % 5) + 5 * ((0) % 5))] = + array[(((0) % 5) + 5 * ((0) % 5))] xor KeccakRoundConstants[indexRound] + } + + private fun keccakAbsorb( + byteState: ByteArray, + data: ByteArray, + dataInBytes: Int, + ) { + keccakPermutationAfterXor(byteState, data, dataInBytes) + } + + private fun keccakExtract1024bits( + byteState: ByteArray, + data: ByteArray, + ) { + System.arraycopy(byteState, 0, data, 0, 128) + } + + private fun keccakExtract( + byteState: ByteArray, + data: ByteArray, + laneCount: Int, + ) { + System.arraycopy(byteState, 0, data, 0, laneCount * 8) + } + + companion object { + private val KeccakRoundConstants: LongArray = keccakInitializeRoundConstants() + + private val KeccakRhoOffsets: IntArray = keccakInitializeRhoOffsets() + + private fun keccakInitializeRoundConstants(): LongArray { + val keccakRoundConstants = LongArray(24) + val lfsrState = ByteArray(1) + + lfsrState[0] = 0x01 + var i: Int + var j: Int + var bitPosition: Int + + i = 0 + while (i < 24) { + keccakRoundConstants[i] = 0 + + j = 0 + while (j < 7) { + bitPosition = (1 shl j) - 1 + + if (lfsr86540(lfsrState)) { + keccakRoundConstants[i] = keccakRoundConstants[i] xor (1L shl bitPosition) + } + j++ + } + i++ + } + + return keccakRoundConstants + } + + private fun lfsr86540(lfsr: ByteArray): Boolean { + val result = (((lfsr[0]).toInt() and 0x01) != 0) + + if (((lfsr[0]).toInt() and 0x80) != 0) { + lfsr[0] = (((lfsr[0]).toInt() shl 1) xor 0x71).toByte() + } else { + lfsr[0] = (lfsr[0].toInt() shl 1).toByte() + } + + return result + } + + private fun keccakInitializeRhoOffsets(): IntArray { + val keccakRhoOffsets = IntArray(25) + var x: Int + var y: Int + var t: Int + var newX: Int + var newY: Int + + keccakRhoOffsets[(((0) % 5) + 5 * ((0) % 5))] = 0 + x = 1 + y = 0 + + t = 0 + while (t < 24) { + keccakRhoOffsets[(((x) % 5) + 5 * ((y) % 5))] = ((t + 1) * (t + 2) / 2) % 64 + newX = (0 * x + 1 * y) % 5 + newY = (2 * x + 3 * y) % 5 + x = newX + y = newY + t++ + } + + return keccakRhoOffsets + } + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Memoable.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Memoable.kt new file mode 100644 index 000000000..f7b873829 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Memoable.kt @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.crypto + +/** + * Interface for Memoable objects. Memoable objects allow the taking of a snapshot of their internal state + * via the [copy()][.copy] method and then resetting the object back to that state later using the + * [reset()][.reset] method. + */ +interface Memoable { + /** + * Produce a copy of this object with its configuration and in its current state. + * + * + * The returned object may be used simply to store the state, or may be used as a similar object + * starting from the copied state. + * + * @return Memoable object + */ + fun copy(): Memoable + + /** + * Restore a copied object state into this object. + * + * + * Implementations of this method *should* try to avoid or minimise memory allocation to perform the reset. + * + * @param other an object originally [copied][.copy] from an object of the same type as this instance. + * @throws ClassCastException if the provided object is not of the correct type. + */ + fun reset(other: Memoable) +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Pack.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Pack.kt new file mode 100644 index 000000000..77ac39362 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Pack.kt @@ -0,0 +1,322 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.crypto + +/** + * Utility methods for converting byte arrays into ints and longs, and back again. + */ +object Pack { + fun bigEndianToShort( + bs: ByteArray, + off: Int, + ): Short { + var off = off + var n = (bs[off].toInt() and 0xff) shl 8 + n = n or (bs[++off].toInt() and 0xff) + return n.toShort() + } + + @JvmStatic + fun bigEndianToInt( + bs: ByteArray, + off: Int, + ): Int { + var off = off + var n = bs[off].toInt() shl 24 + n = n or ((bs[++off].toInt() and 0xff) shl 16) + n = n or ((bs[++off].toInt() and 0xff) shl 8) + n = n or (bs[++off].toInt() and 0xff) + return n + } + + fun bigEndianToInt( + bs: ByteArray, + off: Int, + ns: IntArray, + ) { + var off = off + for (i in ns.indices) { + ns[i] = bigEndianToInt(bs, off) + off += 4 + } + } + + fun intToBigEndian(n: Int): ByteArray { + val bs = ByteArray(4) + intToBigEndian(n, bs, 0) + return bs + } + + @JvmStatic + fun intToBigEndian( + n: Int, + bs: ByteArray, + off: Int, + ) { + var off = off + bs[off] = (n ushr 24).toByte() + bs[++off] = (n ushr 16).toByte() + bs[++off] = (n ushr 8).toByte() + bs[++off] = (n).toByte() + } + + fun intToBigEndian(ns: IntArray): ByteArray { + val bs = ByteArray(4 * ns.size) + intToBigEndian(ns, bs, 0) + return bs + } + + fun intToBigEndian( + ns: IntArray, + bs: ByteArray, + off: Int, + ) { + var off = off + for (i in ns.indices) { + intToBigEndian(ns[i], bs, off) + off += 4 + } + } + + @JvmStatic + fun bigEndianToLong( + bs: ByteArray, + off: Int, + ): Long { + val hi = bigEndianToInt(bs, off) + val lo = bigEndianToInt(bs, off + 4) + return ((hi.toLong() and 0xffffffffL) shl 32) or (lo.toLong() and 0xffffffffL) + } + + fun bigEndianToLong( + bs: ByteArray, + off: Int, + ns: LongArray, + ) { + var off = off + for (i in ns.indices) { + ns[i] = bigEndianToLong(bs, off) + off += 8 + } + } + + fun longToBigEndian(n: Long): ByteArray { + val bs = ByteArray(8) + longToBigEndian(n, bs, 0) + return bs + } + + @JvmStatic + fun longToBigEndian( + n: Long, + bs: ByteArray, + off: Int, + ) { + intToBigEndian((n ushr 32).toInt(), bs, off) + intToBigEndian((n and 0xffffffffL).toInt(), bs, off + 4) + } + + fun longToBigEndian(ns: LongArray): ByteArray { + val bs = ByteArray(8 * ns.size) + longToBigEndian(ns, bs, 0) + return bs + } + + fun longToBigEndian( + ns: LongArray, + bs: ByteArray, + off: Int, + ) { + var off = off + for (i in ns.indices) { + longToBigEndian(ns[i], bs, off) + off += 8 + } + } + + fun littleEndianToShort( + bs: ByteArray, + off: Int, + ): Short { + var off = off + var n = bs[off].toInt() and 0xff + n = n or ((bs[++off].toInt() and 0xff) shl 8) + return n.toShort() + } + + fun littleEndianToInt( + bs: ByteArray, + off: Int, + ): Int { + var off = off + var n = bs[off].toInt() and 0xff + n = n or ((bs[++off].toInt() and 0xff) shl 8) + n = n or ((bs[++off].toInt() and 0xff) shl 16) + n = n or (bs[++off].toInt() shl 24) + return n + } + + fun littleEndianToInt( + bs: ByteArray, + off: Int, + ns: IntArray, + ) { + var off = off + for (i in ns.indices) { + ns[i] = littleEndianToInt(bs, off) + off += 4 + } + } + + fun littleEndianToInt( + bs: ByteArray, + bOff: Int, + ns: IntArray, + nOff: Int, + count: Int, + ) { + var bOff = bOff + for (i in 0.. 14) { + processBlock() + } + + xArray[14] = (bitLength and 0xffffffffL).toInt() + xArray[15] = (bitLength ushr 32).toInt() + } + + private fun unpackWord( + word: Int, + out: ByteArray, + outOff: Int, + ) { + out[outOff] = word.toByte() + out[outOff + 1] = (word ushr 8).toByte() + out[outOff + 2] = (word ushr 16).toByte() + out[outOff + 3] = (word ushr 24).toByte() + } + + override fun doFinal( + out: ByteArray, + outOff: Int, + ): Int { + finish() + + unpackWord(h0, out, outOff) + unpackWord(h1, out, outOff + 4) + unpackWord(h2, out, outOff + 8) + unpackWord(h3, out, outOff + 12) + unpackWord(h4, out, outOff + 16) + + reset() + + return DIGEST_LENGTH + } + + /** + * reset the chaining variables to the IV values. + */ + override fun reset() { + super.reset() + + h0 = 0x67452301 + h1 = -0x10325477 + h2 = -0x67452302 + h3 = 0x10325476 + h4 = -0x3c2d1e10 + + xOff = 0 + + for (i in xArray.indices) { + xArray[i] = 0 + } + } + + /* + * rotate int x left n bits. + */ + private fun rotateLeft( + x: Int, + n: Int, + ): Int = (x shl n) or (x ushr (32 - n)) + + /* + * f1,f2,f3,f4,f5 are the basic RIPEMD160 functions. + * rounds 0-15 + */ + private fun f1( + x: Int, + y: Int, + z: Int, + ): Int = x xor y xor z + + /* + * rounds 16-31 + */ + private fun f2( + x: Int, + y: Int, + z: Int, + ): Int = (x and y) or (x.inv() and z) + + /* + * rounds 32-47 + */ + private fun f3( + x: Int, + y: Int, + z: Int, + ): Int = (x or y.inv()) xor z + + /* + * rounds 48-63 + */ + private fun f4( + x: Int, + y: Int, + z: Int, + ): Int = (x and z) or (y and z.inv()) + + /* + * rounds 64-79 + */ + private fun f5( + x: Int, + y: Int, + z: Int, + ): Int = x xor (y or z.inv()) + + override fun processBlock() { + var a: Int + var aa: Int + var b: Int + var bb: Int + var c: Int + var cc: Int + var d: Int + var dd: Int + var e: Int + var ee: Int + + aa = h0 + a = aa + bb = h1 + b = bb + cc = h2 + c = cc + dd = h3 + d = dd + ee = h4 + e = ee + + // + // Rounds 1 - 16 + // + // left + a = rotateLeft(a + f1(b, c, d) + xArray[0], 11) + e + c = rotateLeft(c, 10) + e = rotateLeft(e + f1(a, b, c) + xArray[1], 14) + d + b = rotateLeft(b, 10) + d = rotateLeft(d + f1(e, a, b) + xArray[2], 15) + c + a = rotateLeft(a, 10) + c = rotateLeft(c + f1(d, e, a) + xArray[3], 12) + b + e = rotateLeft(e, 10) + b = rotateLeft(b + f1(c, d, e) + xArray[4], 5) + a + d = rotateLeft(d, 10) + a = rotateLeft(a + f1(b, c, d) + xArray[5], 8) + e + c = rotateLeft(c, 10) + e = rotateLeft(e + f1(a, b, c) + xArray[6], 7) + d + b = rotateLeft(b, 10) + d = rotateLeft(d + f1(e, a, b) + xArray[7], 9) + c + a = rotateLeft(a, 10) + c = rotateLeft(c + f1(d, e, a) + xArray[8], 11) + b + e = rotateLeft(e, 10) + b = rotateLeft(b + f1(c, d, e) + xArray[9], 13) + a + d = rotateLeft(d, 10) + a = rotateLeft(a + f1(b, c, d) + xArray[10], 14) + e + c = rotateLeft(c, 10) + e = rotateLeft(e + f1(a, b, c) + xArray[11], 15) + d + b = rotateLeft(b, 10) + d = rotateLeft(d + f1(e, a, b) + xArray[12], 6) + c + a = rotateLeft(a, 10) + c = rotateLeft(c + f1(d, e, a) + xArray[13], 7) + b + e = rotateLeft(e, 10) + b = rotateLeft(b + f1(c, d, e) + xArray[14], 9) + a + d = rotateLeft(d, 10) + a = rotateLeft(a + f1(b, c, d) + xArray[15], 8) + e + c = rotateLeft(c, 10) + + // right + aa = rotateLeft(aa + f5(bb, cc, dd) + xArray[5] + 0x50a28be6, 8) + ee + cc = rotateLeft(cc, 10) + ee = rotateLeft(ee + f5(aa, bb, cc) + xArray[14] + 0x50a28be6, 9) + dd + bb = rotateLeft(bb, 10) + dd = rotateLeft(dd + f5(ee, aa, bb) + xArray[7] + 0x50a28be6, 9) + cc + aa = rotateLeft(aa, 10) + cc = rotateLeft(cc + f5(dd, ee, aa) + xArray[0] + 0x50a28be6, 11) + bb + ee = rotateLeft(ee, 10) + bb = rotateLeft(bb + f5(cc, dd, ee) + xArray[9] + 0x50a28be6, 13) + aa + dd = rotateLeft(dd, 10) + aa = rotateLeft(aa + f5(bb, cc, dd) + xArray[2] + 0x50a28be6, 15) + ee + cc = rotateLeft(cc, 10) + ee = rotateLeft(ee + f5(aa, bb, cc) + xArray[11] + 0x50a28be6, 15) + dd + bb = rotateLeft(bb, 10) + dd = rotateLeft(dd + f5(ee, aa, bb) + xArray[4] + 0x50a28be6, 5) + cc + aa = rotateLeft(aa, 10) + cc = rotateLeft(cc + f5(dd, ee, aa) + xArray[13] + 0x50a28be6, 7) + bb + ee = rotateLeft(ee, 10) + bb = rotateLeft(bb + f5(cc, dd, ee) + xArray[6] + 0x50a28be6, 7) + aa + dd = rotateLeft(dd, 10) + aa = rotateLeft(aa + f5(bb, cc, dd) + xArray[15] + 0x50a28be6, 8) + ee + cc = rotateLeft(cc, 10) + ee = rotateLeft(ee + f5(aa, bb, cc) + xArray[8] + 0x50a28be6, 11) + dd + bb = rotateLeft(bb, 10) + dd = rotateLeft(dd + f5(ee, aa, bb) + xArray[1] + 0x50a28be6, 14) + cc + aa = rotateLeft(aa, 10) + cc = rotateLeft(cc + f5(dd, ee, aa) + xArray[10] + 0x50a28be6, 14) + bb + ee = rotateLeft(ee, 10) + bb = rotateLeft(bb + f5(cc, dd, ee) + xArray[3] + 0x50a28be6, 12) + aa + dd = rotateLeft(dd, 10) + aa = rotateLeft(aa + f5(bb, cc, dd) + xArray[12] + 0x50a28be6, 6) + ee + cc = rotateLeft(cc, 10) + + // + // Rounds 16-31 + // + // left + e = rotateLeft(e + f2(a, b, c) + xArray[7] + 0x5a827999, 7) + d + b = rotateLeft(b, 10) + d = rotateLeft(d + f2(e, a, b) + xArray[4] + 0x5a827999, 6) + c + a = rotateLeft(a, 10) + c = rotateLeft(c + f2(d, e, a) + xArray[13] + 0x5a827999, 8) + b + e = rotateLeft(e, 10) + b = rotateLeft(b + f2(c, d, e) + xArray[1] + 0x5a827999, 13) + a + d = rotateLeft(d, 10) + a = rotateLeft(a + f2(b, c, d) + xArray[10] + 0x5a827999, 11) + e + c = rotateLeft(c, 10) + e = rotateLeft(e + f2(a, b, c) + xArray[6] + 0x5a827999, 9) + d + b = rotateLeft(b, 10) + d = rotateLeft(d + f2(e, a, b) + xArray[15] + 0x5a827999, 7) + c + a = rotateLeft(a, 10) + c = rotateLeft(c + f2(d, e, a) + xArray[3] + 0x5a827999, 15) + b + e = rotateLeft(e, 10) + b = rotateLeft(b + f2(c, d, e) + xArray[12] + 0x5a827999, 7) + a + d = rotateLeft(d, 10) + a = rotateLeft(a + f2(b, c, d) + xArray[0] + 0x5a827999, 12) + e + c = rotateLeft(c, 10) + e = rotateLeft(e + f2(a, b, c) + xArray[9] + 0x5a827999, 15) + d + b = rotateLeft(b, 10) + d = rotateLeft(d + f2(e, a, b) + xArray[5] + 0x5a827999, 9) + c + a = rotateLeft(a, 10) + c = rotateLeft(c + f2(d, e, a) + xArray[2] + 0x5a827999, 11) + b + e = rotateLeft(e, 10) + b = rotateLeft(b + f2(c, d, e) + xArray[14] + 0x5a827999, 7) + a + d = rotateLeft(d, 10) + a = rotateLeft(a + f2(b, c, d) + xArray[11] + 0x5a827999, 13) + e + c = rotateLeft(c, 10) + e = rotateLeft(e + f2(a, b, c) + xArray[8] + 0x5a827999, 12) + d + b = rotateLeft(b, 10) + + // right + ee = rotateLeft(ee + f4(aa, bb, cc) + xArray[6] + 0x5c4dd124, 9) + dd + bb = rotateLeft(bb, 10) + dd = rotateLeft(dd + f4(ee, aa, bb) + xArray[11] + 0x5c4dd124, 13) + cc + aa = rotateLeft(aa, 10) + cc = rotateLeft(cc + f4(dd, ee, aa) + xArray[3] + 0x5c4dd124, 15) + bb + ee = rotateLeft(ee, 10) + bb = rotateLeft(bb + f4(cc, dd, ee) + xArray[7] + 0x5c4dd124, 7) + aa + dd = rotateLeft(dd, 10) + aa = rotateLeft(aa + f4(bb, cc, dd) + xArray[0] + 0x5c4dd124, 12) + ee + cc = rotateLeft(cc, 10) + ee = rotateLeft(ee + f4(aa, bb, cc) + xArray[13] + 0x5c4dd124, 8) + dd + bb = rotateLeft(bb, 10) + dd = rotateLeft(dd + f4(ee, aa, bb) + xArray[5] + 0x5c4dd124, 9) + cc + aa = rotateLeft(aa, 10) + cc = rotateLeft(cc + f4(dd, ee, aa) + xArray[10] + 0x5c4dd124, 11) + bb + ee = rotateLeft(ee, 10) + bb = rotateLeft(bb + f4(cc, dd, ee) + xArray[14] + 0x5c4dd124, 7) + aa + dd = rotateLeft(dd, 10) + aa = rotateLeft(aa + f4(bb, cc, dd) + xArray[15] + 0x5c4dd124, 7) + ee + cc = rotateLeft(cc, 10) + ee = rotateLeft(ee + f4(aa, bb, cc) + xArray[8] + 0x5c4dd124, 12) + dd + bb = rotateLeft(bb, 10) + dd = rotateLeft(dd + f4(ee, aa, bb) + xArray[12] + 0x5c4dd124, 7) + cc + aa = rotateLeft(aa, 10) + cc = rotateLeft(cc + f4(dd, ee, aa) + xArray[4] + 0x5c4dd124, 6) + bb + ee = rotateLeft(ee, 10) + bb = rotateLeft(bb + f4(cc, dd, ee) + xArray[9] + 0x5c4dd124, 15) + aa + dd = rotateLeft(dd, 10) + aa = rotateLeft(aa + f4(bb, cc, dd) + xArray[1] + 0x5c4dd124, 13) + ee + cc = rotateLeft(cc, 10) + ee = rotateLeft(ee + f4(aa, bb, cc) + xArray[2] + 0x5c4dd124, 11) + dd + bb = rotateLeft(bb, 10) + + // + // Rounds 32-47 + // + // left + d = rotateLeft(d + f3(e, a, b) + xArray[3] + 0x6ed9eba1, 11) + c + a = rotateLeft(a, 10) + c = rotateLeft(c + f3(d, e, a) + xArray[10] + 0x6ed9eba1, 13) + b + e = rotateLeft(e, 10) + b = rotateLeft(b + f3(c, d, e) + xArray[14] + 0x6ed9eba1, 6) + a + d = rotateLeft(d, 10) + a = rotateLeft(a + f3(b, c, d) + xArray[4] + 0x6ed9eba1, 7) + e + c = rotateLeft(c, 10) + e = rotateLeft(e + f3(a, b, c) + xArray[9] + 0x6ed9eba1, 14) + d + b = rotateLeft(b, 10) + d = rotateLeft(d + f3(e, a, b) + xArray[15] + 0x6ed9eba1, 9) + c + a = rotateLeft(a, 10) + c = rotateLeft(c + f3(d, e, a) + xArray[8] + 0x6ed9eba1, 13) + b + e = rotateLeft(e, 10) + b = rotateLeft(b + f3(c, d, e) + xArray[1] + 0x6ed9eba1, 15) + a + d = rotateLeft(d, 10) + a = rotateLeft(a + f3(b, c, d) + xArray[2] + 0x6ed9eba1, 14) + e + c = rotateLeft(c, 10) + e = rotateLeft(e + f3(a, b, c) + xArray[7] + 0x6ed9eba1, 8) + d + b = rotateLeft(b, 10) + d = rotateLeft(d + f3(e, a, b) + xArray[0] + 0x6ed9eba1, 13) + c + a = rotateLeft(a, 10) + c = rotateLeft(c + f3(d, e, a) + xArray[6] + 0x6ed9eba1, 6) + b + e = rotateLeft(e, 10) + b = rotateLeft(b + f3(c, d, e) + xArray[13] + 0x6ed9eba1, 5) + a + d = rotateLeft(d, 10) + a = rotateLeft(a + f3(b, c, d) + xArray[11] + 0x6ed9eba1, 12) + e + c = rotateLeft(c, 10) + e = rotateLeft(e + f3(a, b, c) + xArray[5] + 0x6ed9eba1, 7) + d + b = rotateLeft(b, 10) + d = rotateLeft(d + f3(e, a, b) + xArray[12] + 0x6ed9eba1, 5) + c + a = rotateLeft(a, 10) + + // right + dd = rotateLeft(dd + f3(ee, aa, bb) + xArray[15] + 0x6d703ef3, 9) + cc + aa = rotateLeft(aa, 10) + cc = rotateLeft(cc + f3(dd, ee, aa) + xArray[5] + 0x6d703ef3, 7) + bb + ee = rotateLeft(ee, 10) + bb = rotateLeft(bb + f3(cc, dd, ee) + xArray[1] + 0x6d703ef3, 15) + aa + dd = rotateLeft(dd, 10) + aa = rotateLeft(aa + f3(bb, cc, dd) + xArray[3] + 0x6d703ef3, 11) + ee + cc = rotateLeft(cc, 10) + ee = rotateLeft(ee + f3(aa, bb, cc) + xArray[7] + 0x6d703ef3, 8) + dd + bb = rotateLeft(bb, 10) + dd = rotateLeft(dd + f3(ee, aa, bb) + xArray[14] + 0x6d703ef3, 6) + cc + aa = rotateLeft(aa, 10) + cc = rotateLeft(cc + f3(dd, ee, aa) + xArray[6] + 0x6d703ef3, 6) + bb + ee = rotateLeft(ee, 10) + bb = rotateLeft(bb + f3(cc, dd, ee) + xArray[9] + 0x6d703ef3, 14) + aa + dd = rotateLeft(dd, 10) + aa = rotateLeft(aa + f3(bb, cc, dd) + xArray[11] + 0x6d703ef3, 12) + ee + cc = rotateLeft(cc, 10) + ee = rotateLeft(ee + f3(aa, bb, cc) + xArray[8] + 0x6d703ef3, 13) + dd + bb = rotateLeft(bb, 10) + dd = rotateLeft(dd + f3(ee, aa, bb) + xArray[12] + 0x6d703ef3, 5) + cc + aa = rotateLeft(aa, 10) + cc = rotateLeft(cc + f3(dd, ee, aa) + xArray[2] + 0x6d703ef3, 14) + bb + ee = rotateLeft(ee, 10) + bb = rotateLeft(bb + f3(cc, dd, ee) + xArray[10] + 0x6d703ef3, 13) + aa + dd = rotateLeft(dd, 10) + aa = rotateLeft(aa + f3(bb, cc, dd) + xArray[0] + 0x6d703ef3, 13) + ee + cc = rotateLeft(cc, 10) + ee = rotateLeft(ee + f3(aa, bb, cc) + xArray[4] + 0x6d703ef3, 7) + dd + bb = rotateLeft(bb, 10) + dd = rotateLeft(dd + f3(ee, aa, bb) + xArray[13] + 0x6d703ef3, 5) + cc + aa = rotateLeft(aa, 10) + + // + // Rounds 48-63 + // + // left + c = rotateLeft(c + f4(d, e, a) + xArray[1] + -0x70e44324, 11) + b + e = rotateLeft(e, 10) + b = rotateLeft(b + f4(c, d, e) + xArray[9] + -0x70e44324, 12) + a + d = rotateLeft(d, 10) + a = rotateLeft(a + f4(b, c, d) + xArray[11] + -0x70e44324, 14) + e + c = rotateLeft(c, 10) + e = rotateLeft(e + f4(a, b, c) + xArray[10] + -0x70e44324, 15) + d + b = rotateLeft(b, 10) + d = rotateLeft(d + f4(e, a, b) + xArray[0] + -0x70e44324, 14) + c + a = rotateLeft(a, 10) + c = rotateLeft(c + f4(d, e, a) + xArray[8] + -0x70e44324, 15) + b + e = rotateLeft(e, 10) + b = rotateLeft(b + f4(c, d, e) + xArray[12] + -0x70e44324, 9) + a + d = rotateLeft(d, 10) + a = rotateLeft(a + f4(b, c, d) + xArray[4] + -0x70e44324, 8) + e + c = rotateLeft(c, 10) + e = rotateLeft(e + f4(a, b, c) + xArray[13] + -0x70e44324, 9) + d + b = rotateLeft(b, 10) + d = rotateLeft(d + f4(e, a, b) + xArray[3] + -0x70e44324, 14) + c + a = rotateLeft(a, 10) + c = rotateLeft(c + f4(d, e, a) + xArray[7] + -0x70e44324, 5) + b + e = rotateLeft(e, 10) + b = rotateLeft(b + f4(c, d, e) + xArray[15] + -0x70e44324, 6) + a + d = rotateLeft(d, 10) + a = rotateLeft(a + f4(b, c, d) + xArray[14] + -0x70e44324, 8) + e + c = rotateLeft(c, 10) + e = rotateLeft(e + f4(a, b, c) + xArray[5] + -0x70e44324, 6) + d + b = rotateLeft(b, 10) + d = rotateLeft(d + f4(e, a, b) + xArray[6] + -0x70e44324, 5) + c + a = rotateLeft(a, 10) + c = rotateLeft(c + f4(d, e, a) + xArray[2] + -0x70e44324, 12) + b + e = rotateLeft(e, 10) + + // right + cc = rotateLeft(cc + f2(dd, ee, aa) + xArray[8] + 0x7a6d76e9, 15) + bb + ee = rotateLeft(ee, 10) + bb = rotateLeft(bb + f2(cc, dd, ee) + xArray[6] + 0x7a6d76e9, 5) + aa + dd = rotateLeft(dd, 10) + aa = rotateLeft(aa + f2(bb, cc, dd) + xArray[4] + 0x7a6d76e9, 8) + ee + cc = rotateLeft(cc, 10) + ee = rotateLeft(ee + f2(aa, bb, cc) + xArray[1] + 0x7a6d76e9, 11) + dd + bb = rotateLeft(bb, 10) + dd = rotateLeft(dd + f2(ee, aa, bb) + xArray[3] + 0x7a6d76e9, 14) + cc + aa = rotateLeft(aa, 10) + cc = rotateLeft(cc + f2(dd, ee, aa) + xArray[11] + 0x7a6d76e9, 14) + bb + ee = rotateLeft(ee, 10) + bb = rotateLeft(bb + f2(cc, dd, ee) + xArray[15] + 0x7a6d76e9, 6) + aa + dd = rotateLeft(dd, 10) + aa = rotateLeft(aa + f2(bb, cc, dd) + xArray[0] + 0x7a6d76e9, 14) + ee + cc = rotateLeft(cc, 10) + ee = rotateLeft(ee + f2(aa, bb, cc) + xArray[5] + 0x7a6d76e9, 6) + dd + bb = rotateLeft(bb, 10) + dd = rotateLeft(dd + f2(ee, aa, bb) + xArray[12] + 0x7a6d76e9, 9) + cc + aa = rotateLeft(aa, 10) + cc = rotateLeft(cc + f2(dd, ee, aa) + xArray[2] + 0x7a6d76e9, 12) + bb + ee = rotateLeft(ee, 10) + bb = rotateLeft(bb + f2(cc, dd, ee) + xArray[13] + 0x7a6d76e9, 9) + aa + dd = rotateLeft(dd, 10) + aa = rotateLeft(aa + f2(bb, cc, dd) + xArray[9] + 0x7a6d76e9, 12) + ee + cc = rotateLeft(cc, 10) + ee = rotateLeft(ee + f2(aa, bb, cc) + xArray[7] + 0x7a6d76e9, 5) + dd + bb = rotateLeft(bb, 10) + dd = rotateLeft(dd + f2(ee, aa, bb) + xArray[10] + 0x7a6d76e9, 15) + cc + aa = rotateLeft(aa, 10) + cc = rotateLeft(cc + f2(dd, ee, aa) + xArray[14] + 0x7a6d76e9, 8) + bb + ee = rotateLeft(ee, 10) + + // + // Rounds 64-79 + // + // left + b = rotateLeft(b + f5(c, d, e) + xArray[4] + -0x56ac02b2, 9) + a + d = rotateLeft(d, 10) + a = rotateLeft(a + f5(b, c, d) + xArray[0] + -0x56ac02b2, 15) + e + c = rotateLeft(c, 10) + e = rotateLeft(e + f5(a, b, c) + xArray[5] + -0x56ac02b2, 5) + d + b = rotateLeft(b, 10) + d = rotateLeft(d + f5(e, a, b) + xArray[9] + -0x56ac02b2, 11) + c + a = rotateLeft(a, 10) + c = rotateLeft(c + f5(d, e, a) + xArray[7] + -0x56ac02b2, 6) + b + e = rotateLeft(e, 10) + b = rotateLeft(b + f5(c, d, e) + xArray[12] + -0x56ac02b2, 8) + a + d = rotateLeft(d, 10) + a = rotateLeft(a + f5(b, c, d) + xArray[2] + -0x56ac02b2, 13) + e + c = rotateLeft(c, 10) + e = rotateLeft(e + f5(a, b, c) + xArray[10] + -0x56ac02b2, 12) + d + b = rotateLeft(b, 10) + d = rotateLeft(d + f5(e, a, b) + xArray[14] + -0x56ac02b2, 5) + c + a = rotateLeft(a, 10) + c = rotateLeft(c + f5(d, e, a) + xArray[1] + -0x56ac02b2, 12) + b + e = rotateLeft(e, 10) + b = rotateLeft(b + f5(c, d, e) + xArray[3] + -0x56ac02b2, 13) + a + d = rotateLeft(d, 10) + a = rotateLeft(a + f5(b, c, d) + xArray[8] + -0x56ac02b2, 14) + e + c = rotateLeft(c, 10) + e = rotateLeft(e + f5(a, b, c) + xArray[11] + -0x56ac02b2, 11) + d + b = rotateLeft(b, 10) + d = rotateLeft(d + f5(e, a, b) + xArray[6] + -0x56ac02b2, 8) + c + a = rotateLeft(a, 10) + c = rotateLeft(c + f5(d, e, a) + xArray[15] + -0x56ac02b2, 5) + b + e = rotateLeft(e, 10) + b = rotateLeft(b + f5(c, d, e) + xArray[13] + -0x56ac02b2, 6) + a + d = rotateLeft(d, 10) + + // right + bb = rotateLeft(bb + f1(cc, dd, ee) + xArray[12], 8) + aa + dd = rotateLeft(dd, 10) + aa = rotateLeft(aa + f1(bb, cc, dd) + xArray[15], 5) + ee + cc = rotateLeft(cc, 10) + ee = rotateLeft(ee + f1(aa, bb, cc) + xArray[10], 12) + dd + bb = rotateLeft(bb, 10) + dd = rotateLeft(dd + f1(ee, aa, bb) + xArray[4], 9) + cc + aa = rotateLeft(aa, 10) + cc = rotateLeft(cc + f1(dd, ee, aa) + xArray[1], 12) + bb + ee = rotateLeft(ee, 10) + bb = rotateLeft(bb + f1(cc, dd, ee) + xArray[5], 5) + aa + dd = rotateLeft(dd, 10) + aa = rotateLeft(aa + f1(bb, cc, dd) + xArray[8], 14) + ee + cc = rotateLeft(cc, 10) + ee = rotateLeft(ee + f1(aa, bb, cc) + xArray[7], 6) + dd + bb = rotateLeft(bb, 10) + dd = rotateLeft(dd + f1(ee, aa, bb) + xArray[6], 8) + cc + aa = rotateLeft(aa, 10) + cc = rotateLeft(cc + f1(dd, ee, aa) + xArray[2], 13) + bb + ee = rotateLeft(ee, 10) + bb = rotateLeft(bb + f1(cc, dd, ee) + xArray[13], 6) + aa + dd = rotateLeft(dd, 10) + aa = rotateLeft(aa + f1(bb, cc, dd) + xArray[14], 5) + ee + cc = rotateLeft(cc, 10) + ee = rotateLeft(ee + f1(aa, bb, cc) + xArray[0], 15) + dd + bb = rotateLeft(bb, 10) + dd = rotateLeft(dd + f1(ee, aa, bb) + xArray[3], 13) + cc + aa = rotateLeft(aa, 10) + cc = rotateLeft(cc + f1(dd, ee, aa) + xArray[9], 11) + bb + ee = rotateLeft(ee, 10) + bb = rotateLeft(bb + f1(cc, dd, ee) + xArray[11], 11) + aa + dd = rotateLeft(dd, 10) + + dd += c + h1 + h1 = h2 + d + ee + h2 = h3 + e + aa + h3 = h4 + a + bb + h4 = h0 + b + cc + h0 = dd + + // + // reset the offset and clean out the word buffer. + // + xOff = 0 + for (i in xArray.indices) { + xArray[i] = 0 + } + } + + override fun copy(): Memoable = RIPEMD160Digest(this) + + override fun reset(other: Memoable) { + val d = other as RIPEMD160Digest + + copyIn(d) + } + + companion object { + private const val DIGEST_LENGTH = 20 + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/CommitmentNotFoundException.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/CommitmentNotFoundException.kt new file mode 100644 index 000000000..f688cb8a3 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/CommitmentNotFoundException.kt @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.exceptions + +class CommitmentNotFoundException( + message: String?, +) : Exception(message) diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/DeserializationException.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/DeserializationException.kt new file mode 100644 index 000000000..9cd75aadb --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/DeserializationException.kt @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.exceptions + +class DeserializationException( + message: String?, +) : Exception(message) diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/ExceededSizeException.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/ExceededSizeException.kt new file mode 100644 index 000000000..adb704dc5 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/ExceededSizeException.kt @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.exceptions + +class ExceededSizeException( + message: String?, +) : Exception(message) diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/UrlException.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/UrlException.kt new file mode 100644 index 000000000..fbc73f64c --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/UrlException.kt @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.exceptions + +class UrlException( + message: String?, +) : Exception(message) diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/VerificationException.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/VerificationException.kt new file mode 100644 index 000000000..f50aabbfd --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/VerificationException.kt @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.exceptions + +class VerificationException( + message: String?, +) : Exception(message) diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/BlockstreamExplorer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/BlockstreamExplorer.kt new file mode 100644 index 000000000..e024986bb --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/BlockstreamExplorer.kt @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.http + +import android.util.Log +import com.vitorpamplona.quartz.nip03Timestamp.ots.BitcoinExplorer +import com.vitorpamplona.quartz.nip03Timestamp.ots.BlockHeader +import java.net.URL +import java.util.concurrent.Executors + +/** + * Copyright (c) 2025 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. + */ +class BlockstreamExplorer : BitcoinExplorer { + /** + * Retrieve the block information from the block hash. + * + * @param hash Hash of the block. + * @return the blockheader of the hash + * @throws Exception desc + */ + @Throws(Exception::class) + override fun block(hash: String): BlockHeader { + val url = URL("$EXPLORA_URL/block/$hash") + val task = Request(url) + val executor = Executors.newSingleThreadExecutor() + val future = executor.submit(task) + val take: Response = future.get() + executor.shutdown() + if (!take.isOk) throw Exception() + + val jsonObject = take.json + val merkleRoot = jsonObject!!.get("merkle_root").asText() + val time = jsonObject.get("timestamp").asInt().toString() + val blockHeader = BlockHeader(merkleRoot, hash, time) + Log.i("BlockstreamExplorer", take.fromUrl + " " + blockHeader) + return blockHeader + // log.warning("Cannot parse merkleroot from body: " + jsonObject + ": " + e.getMessage()); + } + + /** + * Retrieve the block hash from the block height. + * + * @param height Height of the block. + * @return the hash of the block at height height + * @throws Exception desc + */ + @Throws(Exception::class) + override fun blockHash(height: Int): String { + val url = URL("$EXPLORA_URL/block-height/$height") + val task = Request(url) + val executor = Executors.newSingleThreadExecutor() + val future = executor.submit(task) + val take = future.get() + executor.shutdown() + if (!take.isOk) throw Exception() + val blockHash = take.string + Log.i("BlockstreamExplorer", take.fromUrl + " " + blockHash) + return blockHash + } + + companion object { + private const val EXPLORA_URL = "https://blockstream.info/api" + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Calendar.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Calendar.kt new file mode 100644 index 000000000..7af886299 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Calendar.kt @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.http + +import com.vitorpamplona.quartz.nip01Core.core.toHexKey +import com.vitorpamplona.quartz.nip03Timestamp.ots.ICalendar +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.Timestamp +import com.vitorpamplona.quartz.nip03Timestamp.ots.Timestamp.Companion.deserialize +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.CommitmentNotFoundException +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.ExceededSizeException +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.UrlException +import java.net.URL + +/** + * Class representing remote calendar server interface. + */ +class Calendar( + val url: String, +) : ICalendar { + /** + * Submitting a digest to remote calendar. Returns a com.eternitywall.ots.Timestamp committing to that digest. + * + * @param digest The digest hash to send. + * @return the Timestamp received from the calendar. + * @throws ExceededSizeException if response is too big. + * @throws UrlException if url is not reachable. + * @throws DeserializationException if the data is corrupt + */ + @Throws(ExceededSizeException::class, UrlException::class, DeserializationException::class) + override fun submit(digest: ByteArray): Timestamp { + try { + val headers: MutableMap = HashMap() + headers.put("Accept", "application/vnd.opentimestamps.v1") + headers.put("User-Agent", "java-opentimestamps") + headers.put("Content-Type", "application/x-www-form-urlencoded") + + val obj = URL("$url/digest") + val task = Request(obj) + task.setData(digest) + task.setHeaders(headers) + val response = task.call() + val body = response.bytes + if (body.size > 10000) { + throw ExceededSizeException("Calendar response exceeded size limit") + } + + val ctx = StreamDeserializationContext(body) + return deserialize(ctx, digest) + } catch (e: ExceededSizeException) { + throw e + } catch (e: DeserializationException) { + throw e + } catch (e: Exception) { + throw UrlException(e.message) + } + } + + /** + * Get a timestamp for a given commitment. + * + * @param commitment The digest hash to send. + * @return the Timestamp from the calendar server (with blockchain information if already written). + * @throws ExceededSizeException if response is too big. + * @throws UrlException if url is not reachable. + * @throws CommitmentNotFoundException if commit is not found. + * @throws DeserializationException if the data is corrupt + */ + @Throws( + DeserializationException::class, + ExceededSizeException::class, + CommitmentNotFoundException::class, + UrlException::class, + ) + override fun getTimestamp(commitment: ByteArray): Timestamp { + try { + val headers: MutableMap = HashMap() + headers.put("Accept", "application/vnd.opentimestamps.v1") + headers.put("User-Agent", "java-opentimestamps") + headers.put("Content-Type", "application/x-www-form-urlencoded") + + val obj = URL(url + "/timestamp/" + commitment.toHexKey().lowercase()) + val task = Request(obj) + task.setHeaders(headers) + val response = task.call() + val body = response.bytes + if (body.size > 10000) { + throw ExceededSizeException("Calendar response exceeded size limit") + } + + if (!response.isOk) { + throw CommitmentNotFoundException("com.eternitywall.ots.Calendar response a status code != 200 which is: " + response.status) + } + + val ctx = StreamDeserializationContext(body) + + return deserialize(ctx, commitment) + } catch (e: DeserializationException) { + throw e + } catch (e: ExceededSizeException) { + throw e + } catch (e: CommitmentNotFoundException) { + throw e + } catch (e: Exception) { + throw UrlException(e.message) + } + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/CalendarAsyncSubmit.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/CalendarAsyncSubmit.kt new file mode 100644 index 000000000..b03ac6523 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/CalendarAsyncSubmit.kt @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.http + +import com.vitorpamplona.quartz.nip03Timestamp.ots.ICalendarAsyncSubmit +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.Timestamp +import com.vitorpamplona.quartz.nip03Timestamp.ots.Timestamp.Companion.deserialize +import java.net.URL +import java.util.Optional +import java.util.concurrent.ArrayBlockingQueue +import java.util.concurrent.BlockingQueue + +/** + * For making async calls to a calendar server + */ +class CalendarAsyncSubmit( + private val url: String, + private val digest: ByteArray, +) : ICalendarAsyncSubmit { + private var queue: BlockingQueue> = ArrayBlockingQueue(1) + + fun setQueue(queue: BlockingQueue>) { + this.queue = queue + } + + @Throws(Exception::class) + override fun call(): Optional { + val headers: MutableMap = HashMap() + headers.put("Accept", "application/vnd.opentimestamps.v1") + headers.put("User-Agent", "java-opentimestamps") + headers.put("Content-Type", "application/x-www-form-urlencoded") + + val obj = URL("$url/digest") + val task = Request(obj) + task.setData(digest) + task.setHeaders(headers) + val response = task.call() + + if (response.isOk) { + val body = response.bytes + val ctx = StreamDeserializationContext(body) + val timestamp = deserialize(ctx, digest) + val of: Optional = Optional.of(timestamp) + queue.add(of) + return of + } + + queue.add(Optional.empty()) + + return Optional.empty() + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/CalendarPureJavaBuilder.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/CalendarPureJavaBuilder.kt new file mode 100644 index 000000000..a98bcd23d --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/CalendarPureJavaBuilder.kt @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.http + +import com.vitorpamplona.quartz.nip03Timestamp.ots.CalendarBuilder +import com.vitorpamplona.quartz.nip03Timestamp.ots.ICalendar +import com.vitorpamplona.quartz.nip03Timestamp.ots.ICalendarAsyncSubmit + +/** + * Copyright (c) 2025 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. + */ +class CalendarPureJavaBuilder : CalendarBuilder { + override fun newSyncCalendar(url: String): ICalendar = Calendar(url) + + override fun newAsyncCalendar( + url: String, + digest: ByteArray, + ): ICalendarAsyncSubmit = CalendarAsyncSubmit(url, digest) +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Request.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Request.kt new file mode 100644 index 000000000..341b5a0d4 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Request.kt @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.http + +import android.util.Log +import java.io.DataOutputStream +import java.net.HttpURLConnection +import java.net.URL +import java.util.concurrent.Callable +import java.util.zip.GZIPInputStream + +/** + * For making an HTTP request. + */ +class Request( + private val url: URL, +) : Callable { + private var data: ByteArray? = null + private var headers: MutableMap = mutableMapOf() + + fun setData(data: ByteArray?) { + this.data = data + } + + fun setHeaders(headers: MutableMap) { + this.headers = headers + } + + @Throws(Exception::class) + override fun call(): Response { + val response = Response() + + try { + val httpURLConnection = url.openConnection() as HttpURLConnection + httpURLConnection.setReadTimeout(10000) + httpURLConnection.setConnectTimeout(10000) + httpURLConnection.setRequestProperty("User-Agent", "OpenTimestamps Java") + httpURLConnection.setRequestProperty("Accept", "application/json") + httpURLConnection.setRequestProperty("Accept-Encoding", "gzip") + + for (entry in headers.entries) { + httpURLConnection.setRequestProperty(entry.key, entry.value) + } + + if (data != null) { + httpURLConnection.setDoOutput(true) + httpURLConnection.setRequestMethod("POST") + httpURLConnection.setRequestProperty( + "Content-Length", + "" + this.data!!.size.toString(), + ) + val wr = DataOutputStream(httpURLConnection.getOutputStream()) + wr.write(this.data, 0, this.data!!.size) + wr.flush() + wr.close() + } else { + httpURLConnection.setRequestMethod("GET") + } + + httpURLConnection.connect() + + val responseCode = httpURLConnection.getResponseCode() + + Log.i("OpenTimestamp", "$responseCode responseCode ") + + response.status = responseCode + response.fromUrl = url.toString() + var `is` = httpURLConnection.getInputStream() + if ("gzip" == httpURLConnection.getContentEncoding()) { + `is` = GZIPInputStream(`is`) + } + response.setStream(`is`) + } catch (e: Exception) { + Log.w("OpenTimestamp", "$url exception $e") + } + + return response + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Response.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Response.kt new file mode 100644 index 000000000..dc44a417f --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Response.kt @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.http + +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.json.JsonMapper +import java.io.ByteArrayOutputStream +import java.io.IOException +import java.io.InputStream +import java.nio.charset.StandardCharsets + +/** + * Holds the response from an HTTP request. + */ +class Response { + private var stream: InputStream? = null + + var fromUrl: String? = null + var status: Int? = null + + constructor() + + constructor(stream: InputStream) { + this.stream = stream + } + + fun setStream(stream: InputStream) { + this.stream = stream + } + + val isOk: Boolean + get() = this.status != null && 200 == this.status + + fun getStream(): InputStream = this.stream!! + + @get:Throws(IOException::class) + val string: String + get() = kotlin.text.String(this.bytes, StandardCharsets.UTF_8) + + @get:Throws(IOException::class) + val bytes: ByteArray + get() { + val buffer = ByteArrayOutputStream() + var nRead: Int + val data = ByteArray(16384) + + while ((this.stream!!.read(data, 0, data.size).also { nRead = it }) != -1) { + buffer.write(data, 0, nRead) + } + + buffer.flush() + + return buffer.toByteArray() + } + + @get:Throws(IOException::class) + val json: JsonNode? + get() { + val jsonString = this.string + val builder = + JsonMapper.builder().build() + return builder.readTree(jsonString) + } +} diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpBitcoinExplorer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OkHttpBitcoinExplorer.kt similarity index 92% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpBitcoinExplorer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OkHttpBitcoinExplorer.kt index 7ec04b0e9..5df44323a 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpBitcoinExplorer.kt +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OkHttpBitcoinExplorer.kt @@ -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.amethyst.service.ots +package com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp import android.util.Log import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper @@ -61,10 +61,9 @@ class OkHttpBitcoinExplorer( val jsonObject = jacksonObjectMapper().readTree(it.body.string()) - val blockHeader = BlockHeader() - blockHeader.merkleroot = jsonObject["merkle_root"].asText() - blockHeader.setTime(jsonObject["timestamp"].asInt().toString()) - blockHeader.blockHash = hash + val merkleRoot = jsonObject["merkle_root"].asText() + val time = jsonObject["timestamp"].asInt().toString() + val blockHeader = BlockHeader(merkleRoot, hash, time) cache.cacheHeaders.put(hash, blockHeader) return blockHeader } else { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendar.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OkHttpCalendar.kt similarity index 92% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendar.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OkHttpCalendar.kt index b8af7b7ef..20e8d3bf8 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendar.kt +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OkHttpCalendar.kt @@ -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.amethyst.service.ots +package com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp import com.vitorpamplona.quartz.nip03Timestamp.ots.ICalendar import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext @@ -30,6 +30,7 @@ import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.UrlException import com.vitorpamplona.quartz.utils.Hex import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient +import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody /** @@ -57,7 +58,7 @@ class OkHttpCalendar( val requestBody = digest.toRequestBody(mediaType) val request = - okhttp3.Request + Request .Builder() .header("Accept", "application/vnd.opentimestamps.v1") .header("Content-Type", "application/x-www-form-urlencoded") @@ -108,7 +109,7 @@ class OkHttpCalendar( val url = url + "/timestamp/" + Hex.encode(commitment) val request = - okhttp3.Request + Request .Builder() .header("Accept", "application/vnd.opentimestamps.v1") .header("Content-Type", "application/x-www-form-urlencoded") @@ -118,15 +119,10 @@ class OkHttpCalendar( client.newCall(request).execute().use { if (it.isSuccessful) { - val ctx = - StreamDeserializationContext( - it.body.bytes(), - ) + val ctx = StreamDeserializationContext(it.body.bytes()) return Timestamp.deserialize(ctx, commitment) } else { - throw CommitmentNotFoundException( - "Calendar response a status code != 200: " + it.code, - ) + throw CommitmentNotFoundException("Calendar response a status code != 200: " + it.code) } } } catch (e: DeserializationException) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendarAsyncSubmit.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OkHttpCalendarAsyncSubmit.kt similarity index 96% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendarAsyncSubmit.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OkHttpCalendarAsyncSubmit.kt index c412fc0c0..4a8ca9100 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendarAsyncSubmit.kt +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OkHttpCalendarAsyncSubmit.kt @@ -18,13 +18,14 @@ * 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.amethyst.service.ots +package com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp import com.vitorpamplona.quartz.nip03Timestamp.ots.ICalendarAsyncSubmit import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext import com.vitorpamplona.quartz.nip03Timestamp.ots.Timestamp import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient +import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody import java.util.Optional @@ -42,7 +43,7 @@ class OkHttpCalendarAsyncSubmit( val requestBody = digest.toRequestBody(mediaType) val request = - okhttp3.Request + Request .Builder() .header("Accept", "application/vnd.opentimestamps.v1") .header("Content-Type", "application/x-www-form-urlencoded") diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendarBuilder.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OkHttpCalendarBuilder.kt similarity index 96% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendarBuilder.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OkHttpCalendarBuilder.kt index 7b079f1db..691056b87 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendarBuilder.kt +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OkHttpCalendarBuilder.kt @@ -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.amethyst.service.ots +package com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp import com.vitorpamplona.quartz.nip03Timestamp.ots.CalendarBuilder import com.vitorpamplona.quartz.nip03Timestamp.ots.ICalendar diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpOtsResolverBuilder.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OkHttpOtsResolverBuilder.kt similarity index 71% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpOtsResolverBuilder.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OkHttpOtsResolverBuilder.kt index d858cdd6b..39af2cc8f 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpOtsResolverBuilder.kt +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OkHttpOtsResolverBuilder.kt @@ -18,15 +18,15 @@ * 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.amethyst.service.ots +package com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp -import com.vitorpamplona.amethyst.service.okhttp.DualHttpClientManager import com.vitorpamplona.quartz.nip03Timestamp.OtsResolver import com.vitorpamplona.quartz.nip03Timestamp.OtsResolverBuilder +import okhttp3.OkHttpClient class OkHttpOtsResolverBuilder( - val okHttpClients: DualHttpClientManager, - val shouldUseTorForUrl: (String) -> Boolean, + val okHttpClient: (url: String) -> OkHttpClient, + val isTorActive: (url: String) -> Boolean, val cache: OtsBlockHeightCache, ) : OtsResolverBuilder { fun getAPI(usingTor: Boolean) = @@ -36,20 +36,14 @@ class OkHttpOtsResolverBuilder( OkHttpBitcoinExplorer.BLOCKSTREAM_API_URL } - override fun build(): OtsResolver { - val shouldUseTor = shouldUseTorForUrl(OkHttpBitcoinExplorer.MEMPOOL_API_URL) - - return OtsResolver( + override fun build(): OtsResolver = + OtsResolver( explorer = OkHttpBitcoinExplorer( - baseAPI = getAPI(usingTor = shouldUseTor), - client = okHttpClients.getHttpClient(shouldUseTor), + baseAPI = getAPI(usingTor = isTorActive(OkHttpBitcoinExplorer.MEMPOOL_API_URL)), + client = okHttpClient(OkHttpBitcoinExplorer.MEMPOOL_API_URL), cache = cache, ), - calendarBuilder = - OkHttpCalendarBuilder { - okHttpClients.getHttpClient(shouldUseTorForUrl(it)) - }, + calendarBuilder = OkHttpCalendarBuilder { okHttpClient(it) }, ) - } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OtsBlockHeightCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OtsBlockHeightCache.kt similarity index 95% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OtsBlockHeightCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OtsBlockHeightCache.kt index b618fdb28..602f61711 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ots/OtsBlockHeightCache.kt +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/okhttp/OtsBlockHeightCache.kt @@ -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.amethyst.service.ots +package com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp import android.util.LruCache import com.vitorpamplona.quartz.nip03Timestamp.ots.BlockHeader diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/Op.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/Op.kt new file mode 100644 index 000000000..7ec89956f --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/Op.kt @@ -0,0 +1,162 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.op + +import android.util.Log +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamSerializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException + +/** + * Operations are the edges in the timestamp tree, with each operation taking a message and zero or more arguments to produce a result. + */ +abstract class Op : Comparable { + open fun tagName(): String = "" + + open fun tag(): Byte = TAG + + /** + * Serialize operation. + * + * @param ctx The stream serialization context. + */ + open fun serialize(ctx: StreamSerializationContext) { + if (this.tag().toInt() == 0x00) { + Log.e("OpenTimestamp", "No valid serialized Op") + // TODO: Is it OK to just log and carry on? Won't it blow up later? Better to throw? + } + + ctx.writeByte(this.tag()) + } + + /** + * Apply the operation to a message. + * Raises MsgValueError if the message value is invalid, such as it being + * too long, or it causing the result to be too long. + * + * @param msg The message. + * @return the msg after the operation has been applied + */ + open fun call(msg: ByteArray): ByteArray { + if (msg.size > MAX_MSG_LENGTH) { + Log.e("OpenTimestamp", "Error : Message too long;") + return byteArrayOf() // TODO: Is this OK? Won't it blow up later? Better to throw? + } + + val r = this.call(msg) + + if (r.size > MAX_RESULT_LENGTH) { + Log.e("OpenTimestamp", "Error : Result too long;") + // TODO: Is it OK to just log and carry on? Won't it blow up later? Better to throw? + } + + return r + } + + override fun compareTo(other: Op): Int = this.tag() - other.tag() + + companion object { + /** + * Maximum length of an com.vitorpamplona.quartz.ots.op.Op result + * + * + * For a verifier, this limit is what limits the maximum amount of memory you + * need at any one time to verify a particular timestamp path; while verifying + * a particular commitment operation path previously calculated results can be + * discarded. + * + * + * Of course, if everything was a merkle tree you never need to append/prepend + * anything near 4KiB of data; 64 bytes would be plenty even with SHA512. The + * main need for this is compatibility with existing systems like Bitcoin + * timestamps and Certificate Transparency servers. While the pathological + * limits required by both are quite large - 1MB and 16MiB respectively - 4KiB + * is perfectly adequate in both cases for more reasonable usage. + * + * + * @see Op subclasses should set this limit even lower if doing so is appropriate + * for them. + */ + val MAX_RESULT_LENGTH: Int = 4096 + + /** + * Maximum length of the message an com.vitorpamplona.quartz.ots.op.Op can be applied too. + * + * + * Similar to the result length limit, this limit gives implementations a sane + * constraint to work with; the maximum result-length limit implicitly + * constrains maximum message length anyway. + * + * + * com.vitorpamplona.quartz.ots.op.Op subclasses should set this limit even lower if doing so is appropriate + * for them. + */ + val MAX_MSG_LENGTH: Int = 4096 + + val TAG: Byte = 0x00.toByte() + + /** + * Deserialize operation from a buffer. + * + * @param ctx The stream deserialization context. + * @return The subclass Operation. + */ + @Throws(DeserializationException::class) + fun deserialize(ctx: StreamDeserializationContext): Op? { + val tag = ctx.readBytes(1)[0] + + return deserializeFromTag(ctx, tag) + } + + /** + * Deserialize operation from a buffer. + * + * @param ctx The stream deserialization context. + * @param tag The tag of the operation. + * @return The subclass Operation. + */ + @Throws(DeserializationException::class) + fun deserializeFromTag( + ctx: StreamDeserializationContext, + tag: Byte, + ): Op? { + if (tag == OpAppend.TAG) { + return OpAppend.deserializeFromTag(ctx, tag) + } else if (tag == OpPrepend.TAG) { + return OpPrepend.deserializeFromTag(ctx, tag) + } else if (tag == OpSHA1.TAG) { + return OpSHA1.deserializeFromTag(ctx, tag) + } else if (tag == OpSHA256.TAG) { + return OpSHA256.deserializeFromTag(ctx, tag) + } else if (tag == OpRIPEMD160.TAG) { + return OpRIPEMD160.deserializeFromTag(ctx, tag) + } else if (tag == OpKECCAK256.TAG) { + return OpKECCAK256.deserializeFromTag(ctx, tag) + } else { + Log.e( + "OpenTimestamp", + "Unknown operation tag: " + tag + " 0x" + String.format("%02x", tag), + ) + return null // TODO: Is this OK? Won't it blow up later? Better to throw? + } + } + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpAppend.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpAppend.kt new file mode 100644 index 000000000..2d5608b8a --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpAppend.kt @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.op + +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils.arraysConcat +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException + +/** + * Append a suffix to a message. + * + * @see OpBinary + */ +class OpAppend( + arg: ByteArray = byteArrayOf(), +) : OpBinary(arg) { + public override fun tag(): Byte = TAG + + override fun tagName(): String = "append" + + public override fun call(msg: ByteArray): ByteArray = arraysConcat(msg, this.arg) + + override fun equals(other: Any?): Boolean { + if (other !is OpAppend) { + return false + } + + return this.arg.contentEquals(other.arg) + } + + override fun hashCode(): Int = TAG.toInt() xor this.arg.contentHashCode() + + companion object { + val TAG: Byte = 0xf0.toByte() + + @Throws(DeserializationException::class) + fun deserializeFromTag( + ctx: StreamDeserializationContext, + tag: Byte, + ): Op? = OpBinary.deserializeFromTag(ctx, tag) + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpBinary.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpBinary.kt new file mode 100644 index 000000000..323c24c1d --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpBinary.kt @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.op + +import android.util.Log +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamSerializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils.compare +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException +import com.vitorpamplona.quartz.utils.Hex.encode + +/** + * Operations that act on a message and a single argument. + * + * @see OpUnary + */ +abstract class OpBinary( + val arg: ByteArray = byteArrayOf(), +) : Op(), + Comparable { + public override fun tagName(): String = "" + + public override fun serialize(ctx: StreamSerializationContext) { + super.serialize(ctx) + ctx.writeVarbytes(this.arg) + } + + override fun toString(): String = this.tagName() + ' ' + encode(this.arg).lowercase() + + override fun compareTo(other: Op): Int { + if (other is OpBinary && this.tag() == other.tag()) { + return compare(this.arg, other.arg) + } + + return this.tag() - other.tag() + } + + override fun hashCode(): Int = TAG.toInt() xor this.arg.contentHashCode() + + companion object { + @JvmStatic + @Throws(DeserializationException::class) + fun deserializeFromTag( + ctx: StreamDeserializationContext, + tag: Byte, + ): Op? { + val arg = ctx.readVarbytes(MAX_RESULT_LENGTH, 1) + + if (tag == OpAppend.TAG) { + return OpAppend(arg) + } else if (tag == OpPrepend.TAG) { + return OpPrepend(arg) + } else { + Log.e( + "OpenTimestamp", + "Unknown operation tag: " + tag + " 0x" + String.format("%02x", tag), + ) + return null // TODO: Is this OK? Won't it blow up later? Better to throw? + } + } + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpCrypto.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpCrypto.kt new file mode 100644 index 000000000..a54907c44 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpCrypto.kt @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.op + +import android.util.Log +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext +import java.io.File +import java.io.FileInputStream +import java.io.IOException +import java.io.InputStream +import java.security.MessageDigest +import java.security.NoSuchAlgorithmException + +/** + * Cryptographic transformations. + * These transformations have the unique property that for any length message, + * the size of the result they return is fixed. Additionally, they're the only + * type of operation that can be applied directly to a stream. + * + * @see OpUnary + */ +abstract class OpCrypto internal constructor() : OpUnary() { + abstract fun hashLibName(): String + + abstract fun digestLength(): Int + + override fun call(msg: ByteArray): ByteArray { + // For Sha1 & Sha256 use java.security.MessageDigest library + try { + val digest = MessageDigest.getInstance(this.hashLibName()) + val hash = digest.digest(msg) + + return hash + } catch (e: NoSuchAlgorithmException) { + Log.e("OpenTimestamp", "NoSuchAlgorithmException") + e.printStackTrace() + + return byteArrayOf() // TODO: Is this OK? Won't it blow up later? Better to throw? + } + } + + @Throws(NoSuchAlgorithmException::class) + fun hashFd(ctx: StreamDeserializationContext): ByteArray { + val digest = MessageDigest.getInstance(this.hashLibName()) + var chunk = ctx.read(1048576) + + while (chunk != null && chunk.size > 0) { + digest.update(chunk) + chunk = ctx.read(1048576) + } + + val hash = digest.digest() + + return hash + } + + @Throws(IOException::class, NoSuchAlgorithmException::class) + fun hashFd(file: File?): ByteArray = hashFd(FileInputStream(file)) + + @Throws(IOException::class, NoSuchAlgorithmException::class) + fun hashFd(bytes: ByteArray): ByteArray { + val ctx = StreamDeserializationContext(bytes) + + return hashFd(ctx) + } + + @Throws(IOException::class, NoSuchAlgorithmException::class) + fun hashFd(inputStream: InputStream): ByteArray { + val digest = MessageDigest.getInstance(this.hashLibName()) + val chunk = ByteArray(1048576) + var count = inputStream.read(chunk, 0, 1048576) + + while (count >= 0) { + digest.update(chunk, 0, count) + count = inputStream.read(chunk, 0, 1048576) + } + + inputStream.close() + val hash = digest.digest() + + return hash + } + + companion object { + @JvmStatic + fun deserializeFromTag( + ctx: StreamDeserializationContext, + tag: Byte, + ): Op? = OpUnary.deserializeFromTag(ctx, tag) + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpKECCAK256.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpKECCAK256.kt new file mode 100644 index 000000000..78a65dfb5 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpKECCAK256.kt @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.op + +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.crypto.KeccakDigest + +/** + * Cryptographic Keccak256 operation. + * Cryptographic operation tag numbers taken from RFC4880, although it's not + * guaranteed that they'll continue to match that RFC in the future. + * + * @see OpCrypto + */ +class OpKECCAK256 : OpCrypto() { + private val digest = KeccakDigest(256) + + override fun tag(): Byte = TAG + + override fun tagName(): String = "keccak256" + + override fun hashLibName(): String = "keccak256" + + override fun digestLength(): Int = digest.getDigestSize() + + override fun call(msg: ByteArray): ByteArray { + digest.update(msg, 0, msg.size) + val hash = ByteArray(digest.getDigestSize()) + digest.doFinal(hash, 0) + + return hash + } + + override fun equals(other: Any?): Boolean = (other is OpKECCAK256) + + companion object { + val TAG: Byte = 103.toByte() + + fun deserializeFromTag( + ctx: StreamDeserializationContext, + tag: Byte, + ): Op? = OpCrypto.deserializeFromTag(ctx, tag) + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpPrepend.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpPrepend.kt new file mode 100644 index 000000000..e88d1c6b3 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpPrepend.kt @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.op + +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils.arraysConcat +import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException + +/** + * Prepend a prefix to a message. + * + * @see OpBinary + */ +class OpPrepend( + arg: ByteArray = byteArrayOf(), +) : OpBinary(arg) { + public override fun tag(): Byte = TAG + + override fun tagName(): String = "prepend" + + public override fun call(msg: ByteArray): ByteArray = arraysConcat(this.arg, msg) + + override fun equals(other: Any?): Boolean { + if (other !is OpPrepend) { + return false + } + + return this.arg.contentEquals(other.arg) + } + + public override fun hashCode(): Int = TAG.toInt() xor this.arg.contentHashCode() + + companion object { + val TAG: Byte = 0xf1.toByte() + + @Throws(DeserializationException::class) + fun deserializeFromTag( + ctx: StreamDeserializationContext, + tag: Byte, + ): Op? = OpBinary.deserializeFromTag(ctx, tag) + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpRIPEMD160.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpRIPEMD160.kt new file mode 100644 index 000000000..6eee1675d --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpRIPEMD160.kt @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.op + +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext +import com.vitorpamplona.quartz.nip03Timestamp.ots.crypto.RIPEMD160Digest + +/** + * Cryptographic RIPEMD160 operation. + * Cryptographic operation tag numbers taken from RFC4880, although it's not + * guaranteed that they'll continue to match that RFC in the future. + * + * @see OpCrypto + */ +class OpRIPEMD160 : OpCrypto() { + override fun tag(): Byte = TAG + + override fun tagName(): String = "ripemd160" + + override fun hashLibName(): String = "ripemd160" + + override fun digestLength(): Int = 20 + + override fun call(msg: ByteArray): ByteArray { + val digest = RIPEMD160Digest() + digest.update(msg, 0, msg.size) + val hash = ByteArray(digest.getDigestSize()) + digest.doFinal(hash, 0) + + return hash + } + + override fun equals(other: Any?): Boolean = (other is OpRIPEMD160) + + override fun hashCode(): Int = TAG.toInt() + + companion object { + val TAG: Byte = 0x03 + + fun deserializeFromTag( + ctx: StreamDeserializationContext, + tag: Byte, + ): Op? = OpCrypto.deserializeFromTag(ctx, tag) + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA1.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA1.kt new file mode 100644 index 000000000..078a73755 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA1.kt @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.op + +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext + +/** + * Cryptographic SHA1 operation. + * Cryptographic operation tag numbers taken from RFC4880, although it's not + * guaranteed that they'll continue to match that RFC in the future. + * Remember that for timestamping, hash algorithms with collision attacks + * *are* secure! We've still proven that both messages existed prior to some + * point in time - the fact that they both have the same hash digest doesn't + * change that. + * Heck, even md5 is still secure enough for timestamping... but that's + * pushing our luck... + * + * @see OpCrypto + */ +class OpSHA1 : OpCrypto() { + public override fun tag(): Byte = TAG + + override fun tagName(): String = "sha1" + + public override fun hashLibName(): String = "SHA-1" + + public override fun digestLength(): Int = 20 + + override fun call(msg: ByteArray): ByteArray = super.call(msg) + + override fun equals(other: Any?): Boolean = (other is OpSHA1) + + override fun hashCode(): Int = TAG.toInt() + + companion object { + val TAG: Byte = 0x02 + + fun deserializeFromTag( + ctx: StreamDeserializationContext, + tag: Byte, + ): Op? = OpCrypto.deserializeFromTag(ctx, tag) + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA256.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA256.kt new file mode 100644 index 000000000..6fe98a6c9 --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA256.kt @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.op + +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext + +/** + * Cryptographic SHA256 operation. + * Cryptographic operation tag numbers taken from RFC4880, although it's not + * guaranteed that they'll continue to match that RFC in the future. + * + * @see OpCrypto + */ +class OpSHA256 : OpCrypto() { + override fun tag(): Byte = TAG + + override fun tagName(): String = "sha256" + + override fun hashLibName(): String = "SHA-256" + + override fun digestLength(): Int = 32 + + override fun call(msg: ByteArray): ByteArray = super.call(msg) + + override fun equals(other: Any?): Boolean = (other is OpSHA256) + + override fun hashCode(): Int = TAG.toInt() + + companion object { + val TAG: Byte = 0x08 + + fun deserializeFromTag( + ctx: StreamDeserializationContext, + tag: Byte, + ): Op? = OpCrypto.deserializeFromTag(ctx, tag) + } +} diff --git a/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpUnary.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpUnary.kt new file mode 100644 index 000000000..bdd23920b --- /dev/null +++ b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpUnary.kt @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2025 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.nip03Timestamp.ots.op + +import android.util.Log +import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext + +/** + * Operations that act on a single message. + * + * @see Op + */ +abstract class OpUnary : Op() { + override fun tagName(): String = "" + + override fun toString(): String = tagName() + + companion object { + fun deserializeFromTag( + ctx: StreamDeserializationContext, + tag: Byte, + ): Op? = + when (tag) { + OpSHA1.TAG -> OpSHA1() + OpSHA256.TAG -> OpSHA256() + OpRIPEMD160.TAG -> OpRIPEMD160() + OpKECCAK256.TAG -> OpKECCAK256() + else -> { + Log.e("OpenTimestamp", "Unknown operation tag: $tag") + + null // TODO: Is this OK? Won't it blow up later? Better to throw? + } + } + } +} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/tags/TargetEventKindTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/tags/TargetEventKindTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/tags/TargetEventKindTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/tags/TargetEventKindTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/tags/TargetEventTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/tags/TargetEventTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/tags/TargetEventTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip03Timestamp/tags/TargetEventTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip04Dm/PrivateDMCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip04Dm/PrivateDMCache.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip04Dm/PrivateDMCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip04Dm/PrivateDMCache.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip04Dm/crypto/AESCBC.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip04Dm/crypto/AESCBC.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip04Dm/crypto/AESCBC.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip04Dm/crypto/AESCBC.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip04Dm/crypto/EncryptedInfo.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip04Dm/crypto/EncryptedInfo.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip04Dm/crypto/EncryptedInfo.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip04Dm/crypto/EncryptedInfo.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip04Dm/crypto/Encryption.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip04Dm/crypto/Encryption.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip04Dm/crypto/Encryption.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip04Dm/crypto/Encryption.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip04Dm/crypto/Nip04.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip04Dm/crypto/Nip04.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip04Dm/crypto/Nip04.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip04Dm/crypto/Nip04.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip04Dm/messages/PrivateDmEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip04Dm/messages/PrivateDmEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip04Dm/messages/PrivateDmEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip04Dm/messages/PrivateDmEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip04Dm/messages/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip04Dm/messages/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip04Dm/messages/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip04Dm/messages/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip05DnsIdentifiers/Nip05.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/Nip05.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip05DnsIdentifiers/Nip05.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/Nip05.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip06KeyDerivation/Bip32SeedDerivation.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Bip32SeedDerivation.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip06KeyDerivation/Bip32SeedDerivation.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Bip32SeedDerivation.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39KeyPath.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39KeyPath.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39KeyPath.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39KeyPath.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39Mnemonics.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39Mnemonics.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39Mnemonics.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Bip39Mnemonics.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip06KeyDerivation/Nip06.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Nip06.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip06KeyDerivation/Nip06.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip06KeyDerivation/Nip06.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip09Deletions/DeletionEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip09Deletions/DeletionEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip09Deletions/DeletionEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip09Deletions/DeletionEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip09Deletions/DeletionIndex.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip09Deletions/DeletionIndex.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip09Deletions/DeletionIndex.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip09Deletions/DeletionIndex.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/BaseNoteEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/BaseNoteEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/BaseNoteEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/BaseNoteEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/BaseThreadedEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/BaseThreadedEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/BaseThreadedEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/BaseThreadedEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/TextNoteEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/TextNoteEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/TextNoteEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/TextNoteEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/content/ContentHashTags.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/content/ContentHashTags.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/content/ContentHashTags.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/content/ContentHashTags.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/content/IndexedTags.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/content/IndexedTags.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/content/IndexedTags.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/content/IndexedTags.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/content/NostrUris.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/content/NostrUris.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/content/NostrUris.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/content/NostrUris.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/content/Urls.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/content/Urls.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/content/Urls.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/content/Urls.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/MarkedETag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/tags/MarkedETag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/MarkedETag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/tags/MarkedETag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/Positional.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/tags/Positional.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/Positional.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/tags/Positional.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/ReplyBuilder.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/tags/ReplyBuilder.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/ReplyBuilder.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/tags/ReplyBuilder.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/tags/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip10Notes/tags/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip11RelayInfo/Nip11RelayInformation.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip11RelayInfo/Nip11RelayInformation.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip11RelayInfo/Nip11RelayInformation.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip11RelayInfo/Nip11RelayInformation.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/miner/ByteArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/miner/ByteArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/miner/ByteArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/miner/ByteArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/miner/MiningBuffer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/miner/MiningBuffer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/miner/MiningBuffer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/miner/MiningBuffer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/miner/PoWMiner.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/miner/PoWMiner.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/miner/PoWMiner.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/miner/PoWMiner.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/miner/PoWRankEvaluator.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/miner/PoWRankEvaluator.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/miner/PoWRankEvaluator.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/miner/PoWRankEvaluator.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/tags/PoWTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/tags/PoWTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/tags/PoWTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip13Pow/tags/PoWTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip14Subject/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip14Subject/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip14Subject/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip14Subject/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip14Subject/SubjectTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip14Subject/SubjectTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip14Subject/SubjectTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip14Subject/SubjectTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip14Subject/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip14Subject/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip14Subject/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip14Subject/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip14Subject/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip14Subject/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip14Subject/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip14Subject/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/NIP17Factory.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/NIP17Factory.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/NIP17Factory.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/NIP17Factory.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/base/BaseDMGroupEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/base/BaseDMGroupEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/base/BaseDMGroupEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/base/BaseDMGroupEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/base/ChatroomKey.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/base/ChatroomKey.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/base/ChatroomKey.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/base/ChatroomKey.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/base/ChatroomKeyable.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/base/ChatroomKeyable.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/base/ChatroomKeyable.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/base/ChatroomKeyable.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/base/NIP17Group.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/base/NIP17Group.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/base/NIP17Group.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/base/NIP17Group.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/ChatMessageEncryptedFileHeaderEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/ChatMessageEncryptedFileHeaderEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/ChatMessageEncryptedFileHeaderEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/ChatMessageEncryptedFileHeaderEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/encryption/AESGCM.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/encryption/AESGCM.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/encryption/AESGCM.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/encryption/AESGCM.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/encryption/NostrCipher.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/encryption/NostrCipher.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/encryption/NostrCipher.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/encryption/NostrCipher.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionAlgo.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionAlgo.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionAlgo.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionAlgo.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionKey.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionKey.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionKey.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionKey.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionNonce.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionNonce.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionNonce.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionNonce.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/FileTypeTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/tags/FileTypeTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/FileTypeTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/files/tags/FileTypeTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/messages/ChatMessageEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/messages/ChatMessageEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/messages/ChatMessageEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/messages/ChatMessageEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/messages/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/messages/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/messages/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/messages/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/settings/ChatMessageRelayListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/settings/ChatMessageRelayListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/settings/ChatMessageRelayListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/settings/ChatMessageRelayListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/settings/tags/RelayTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/settings/tags/RelayTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/settings/tags/RelayTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip17Dm/settings/tags/RelayTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/GenericRepostEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/GenericRepostEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/GenericRepostEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/GenericRepostEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/RepostEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/RepostEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/RepostEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/RepostEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/EntityExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/quotes/EntityExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/EntityExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/quotes/EntityExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/quotes/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/quotes/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QAddressableTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/quotes/QAddressableTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QAddressableTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/quotes/QAddressableTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QEventTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/quotes/QEventTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QEventTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/quotes/QEventTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/quotes/QTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/quotes/QTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/ATagExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/ATagExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/ATagExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/ATagExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/ByteArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/ByteArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/ByteArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/ByteArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/ListEntityExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/ListEntityExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/ListEntityExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/ListEntityExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/Nip19Parser.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/Nip19Parser.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/Nip19Parser.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/Nip19Parser.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/TlvBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/TlvBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/TlvBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/TlvBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/TlvTypes.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/TlvTypes.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/TlvTypes.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/TlvTypes.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/bech32/Bech32Util.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/bech32/Bech32Util.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/bech32/Bech32Util.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/bech32/Bech32Util.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/Entity.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/Entity.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/Entity.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/Entity.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NAddress.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NAddress.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NAddress.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NAddress.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NEmbed.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NEmbed.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NEmbed.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NEmbed.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NNote.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NNote.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NNote.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NNote.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NProfile.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NProfile.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NProfile.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NProfile.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NPub.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NPub.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NPub.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NPub.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NRelay.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NRelay.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NRelay.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NRelay.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NSec.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NSec.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NSec.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/entities/NSec.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/tlv/Tlv.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/tlv/Tlv.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/tlv/Tlv.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/tlv/Tlv.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/tlv/TlvBuilder.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/tlv/TlvBuilder.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/tlv/TlvBuilder.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/tlv/TlvBuilder.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip21UriScheme/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip21UriScheme/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip21UriScheme/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip21UriScheme/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/CommentEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/CommentEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/CommentEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/CommentEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/RootScope.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/RootScope.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/RootScope.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/RootScope.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAddressTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAddressTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAddressTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAddressTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAuthorTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAuthorTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAuthorTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAuthorTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyEventTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/ReplyEventTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyEventTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/ReplyEventTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyIdentifierTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/ReplyIdentifierTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyIdentifierTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/ReplyIdentifierTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyKindTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/ReplyKindTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyKindTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/ReplyKindTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootAddressTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/RootAddressTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootAddressTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/RootAddressTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootAuthorTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/RootAuthorTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootAuthorTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/RootAuthorTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootEventTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/RootEventTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootEventTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/RootEventTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootIdentifierTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/RootIdentifierTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootIdentifierTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/RootIdentifierTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootKindTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/RootKindTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootKindTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip22Comments/tags/RootKindTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/LongTextNoteEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip23LongContent/LongTextNoteEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/LongTextNoteEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip23LongContent/LongTextNoteEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip23LongContent/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip23LongContent/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/ImageTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip23LongContent/tags/ImageTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/ImageTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip23LongContent/tags/ImageTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/PublishedAtTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip23LongContent/tags/PublishedAtTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/PublishedAtTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip23LongContent/tags/PublishedAtTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/SummaryTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip23LongContent/tags/SummaryTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/SummaryTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip23LongContent/tags/SummaryTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/TitleTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip23LongContent/tags/TitleTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/TitleTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip23LongContent/tags/TitleTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip25Reactions/ReactionEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip25Reactions/ReactionEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip25Reactions/ReactionEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip25Reactions/ReactionEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelCreateEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelCreateEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelCreateEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelCreateEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelHideMessageEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelHideMessageEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelHideMessageEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelHideMessageEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMetadataEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMetadataEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMetadataEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMetadataEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMuteUserEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMuteUserEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMuteUserEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMuteUserEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/base/BasePublicChatEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/base/BasePublicChatEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/base/BasePublicChatEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/base/BasePublicChatEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/base/ChannelData.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/base/ChannelData.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/base/ChannelData.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/base/ChannelData.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/base/IsInPublicChatChannel.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/base/IsInPublicChatChannel.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/base/IsInPublicChatChannel.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/base/IsInPublicChatChannel.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/base/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/base/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/base/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/base/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/list/ChannelListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/list/ChannelListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/list/ChannelListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/list/ChannelListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/list/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/list/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/list/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/list/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/list/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/list/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/list/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/list/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/list/tags/ChannelTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/list/tags/ChannelTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/list/tags/ChannelTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/list/tags/ChannelTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/message/ChannelMessageEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/message/ChannelMessageEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/message/ChannelMessageEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip28PublicChat/message/ChannelMessageEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/CustomEmoji.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/CustomEmoji.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/CustomEmoji.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/CustomEmoji.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/EmojiUrlTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/EmojiUrlTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/EmojiUrlTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/EmojiUrlTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/pack/EmojiPackEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/pack/EmojiPackEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/pack/EmojiPackEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/pack/EmojiPackEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/selection/EmojiPackSelectionEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/selection/EmojiPackSelectionEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/selection/EmojiPackSelectionEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/selection/EmojiPackSelectionEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/selection/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/selection/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/selection/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip30CustomEmoji/selection/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip31Alts/AltTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip31Alts/AltTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip31Alts/AltTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip31Alts/AltTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip31Alts/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip31Alts/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip31Alts/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip31Alts/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip31Alts/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip31Alts/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip31Alts/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip31Alts/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip31Alts/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip31Alts/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip31Alts/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip31Alts/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/issue/GitIssueEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/issue/GitIssueEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/issue/GitIssueEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/issue/GitIssueEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/issue/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/issue/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/issue/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/issue/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/patch/GitPatchEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/patch/GitPatchEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/patch/GitPatchEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/patch/GitPatchEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/reply/GitReplyEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/reply/GitReplyEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/reply/GitReplyEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/reply/GitReplyEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/reply/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/reply/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/reply/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/reply/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/GitRepositoryEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/repository/GitRepositoryEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/GitRepositoryEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/repository/GitRepositoryEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/repository/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/repository/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/CloneTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/repository/tags/CloneTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/CloneTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/repository/tags/CloneTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/DescriptionTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/repository/tags/DescriptionTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/DescriptionTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/repository/tags/DescriptionTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/NameTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/repository/tags/NameTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/NameTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/repository/tags/NameTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/WebTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/repository/tags/WebTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/WebTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip34Git/repository/tags/WebTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/DefaultTrackers.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/DefaultTrackers.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/DefaultTrackers.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/DefaultTrackers.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/TorrentCommentEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/TorrentCommentEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/TorrentCommentEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/TorrentCommentEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/TorrentEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/TorrentEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/TorrentEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/TorrentEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/BtihTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/tags/BtihTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/BtihTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/tags/BtihTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/FileTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/tags/FileTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/FileTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/tags/FileTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/InfoHashTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/tags/InfoHashTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/InfoHashTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/tags/InfoHashTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/TrackerTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/tags/TrackerTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/TrackerTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip35Torrents/tags/TrackerTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip36SensitiveContent/ContentWarningTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/ContentWarningTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip36SensitiveContent/ContentWarningTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/ContentWarningTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip36SensitiveContent/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip36SensitiveContent/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip36SensitiveContent/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip36SensitiveContent/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip36SensitiveContent/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip36SensitiveContent/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip36SensitiveContent/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip37Drafts/DraftWrapCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip37Drafts/DraftWrapCache.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip37Drafts/DraftWrapCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip37Drafts/DraftWrapCache.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip37Drafts/DraftWrapEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip37Drafts/DraftWrapEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip37Drafts/DraftWrapEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip37Drafts/DraftWrapEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip37Drafts/ExposeInDraft.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip37Drafts/ExposeInDraft.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip37Drafts/ExposeInDraft.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip37Drafts/ExposeInDraft.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip37Drafts/privateOutbox/PrivateOutboxRelayListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip37Drafts/privateOutbox/PrivateOutboxRelayListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip37Drafts/privateOutbox/PrivateOutboxRelayListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip37Drafts/privateOutbox/PrivateOutboxRelayListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip38UserStatus/StatusEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip38UserStatus/StatusEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip38UserStatus/StatusEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip38UserStatus/StatusEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/GitHubIdentity.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/GitHubIdentity.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/GitHubIdentity.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/GitHubIdentity.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/IdentityClaimTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/IdentityClaimTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/IdentityClaimTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/IdentityClaimTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/MastodonIdentity.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/MastodonIdentity.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/MastodonIdentity.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/MastodonIdentity.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/TelegramIdentity.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/TelegramIdentity.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/TelegramIdentity.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/TelegramIdentity.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/TwitterIdentity.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/TwitterIdentity.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/TwitterIdentity.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/TwitterIdentity.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/UnsupportedIdentity.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/UnsupportedIdentity.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip39ExtIdentities/UnsupportedIdentity.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip39ExtIdentities/UnsupportedIdentity.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip40Expiration/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip40Expiration/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip40Expiration/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip40Expiration/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip40Expiration/ExpirationTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip40Expiration/ExpirationTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip40Expiration/ExpirationTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip40Expiration/ExpirationTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip40Expiration/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip40Expiration/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip40Expiration/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip40Expiration/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip40Expiration/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip40Expiration/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip40Expiration/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip40Expiration/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip42RelayAuth/RelayAuthEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip42RelayAuth/RelayAuthEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip42RelayAuth/RelayAuthEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip42RelayAuth/RelayAuthEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip42RelayAuth/tags/ChallengeTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip42RelayAuth/tags/ChallengeTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip42RelayAuth/tags/ChallengeTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip42RelayAuth/tags/ChallengeTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip42RelayAuth/tags/RelayTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip42RelayAuth/tags/RelayTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip42RelayAuth/tags/RelayTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip42RelayAuth/tags/RelayTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip44Encryption/EncryptedInfoString.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip44Encryption/EncryptedInfoString.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip44Encryption/EncryptedInfoString.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip44Encryption/EncryptedInfoString.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip44Encryption/Nip44.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip44Encryption/Nip44.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip44Encryption/Nip44.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip44Encryption/Nip44.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip44Encryption/Nip44v1.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip44Encryption/Nip44v1.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip44Encryption/Nip44v1.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip44Encryption/Nip44v1.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip44Encryption/Nip44v2.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip44Encryption/Nip44v2.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip44Encryption/Nip44v2.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip44Encryption/Nip44v2.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip44Encryption/SharedKeyCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip44Encryption/SharedKeyCache.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip44Encryption/SharedKeyCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip44Encryption/SharedKeyCache.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip44Encryption/crypto/Hkdf.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip44Encryption/crypto/Hkdf.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip44Encryption/crypto/Hkdf.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip44Encryption/crypto/Hkdf.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerMessage.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerMessage.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerMessage.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerMessage.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequest.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequest.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequest.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequest.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestConnect.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestConnect.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestConnect.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestConnect.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestGetPublicKey.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestGetPublicKey.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestGetPublicKey.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestGetPublicKey.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestGetRelays.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestGetRelays.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestGetRelays.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestGetRelays.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip04Decrypt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip04Decrypt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip04Decrypt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip04Decrypt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip04Encrypt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip04Encrypt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip04Encrypt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip04Encrypt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip44Decrypt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip44Decrypt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip44Decrypt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip44Decrypt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip44Encrypt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip44Encrypt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip44Encrypt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestNip44Encrypt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestPing.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestPing.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestPing.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestPing.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestSign.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestSign.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestSign.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerRequestSign.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponse.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponse.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponse.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponse.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseAck.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseAck.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseAck.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseAck.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseDecrypt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseDecrypt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseDecrypt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseDecrypt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseEncrypt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseEncrypt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseEncrypt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseEncrypt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseError.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseError.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseError.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseError.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseGetRelays.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseGetRelays.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseGetRelays.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseGetRelays.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponsePong.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponsePong.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponsePong.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponsePong.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponsePublicKey.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponsePublicKey.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponsePublicKey.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponsePublicKey.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/NostrConnectEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/NostrConnectEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip46RemoteSigner/NostrConnectEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/NostrConnectEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/LnZapPaymentRequestEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/LnZapPaymentRequestEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/LnZapPaymentRequestEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/LnZapPaymentRequestEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/LnZapPaymentResponseEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/LnZapPaymentResponseEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/LnZapPaymentResponseEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/LnZapPaymentResponseEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/Nip47WalletConnect.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/Nip47WalletConnect.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/Nip47WalletConnect.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/Nip47WalletConnect.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/NostrWalletConnectRequestCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/NostrWalletConnectRequestCache.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/NostrWalletConnectRequestCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/NostrWalletConnectRequestCache.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/NostrWalletConnectResponseCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/NostrWalletConnectResponseCache.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/NostrWalletConnectResponseCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/NostrWalletConnectResponseCache.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/Request.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/Request.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/Request.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/Request.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/RequestDeserializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/RequestDeserializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/RequestDeserializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/RequestDeserializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/Response.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/Response.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/Response.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/Response.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/ResponseDeserializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/ResponseDeserializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip47WalletConnect/ResponseDeserializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip47WalletConnect/ResponseDeserializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip48ProxyTags/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip48ProxyTags/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip48ProxyTags/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip48ProxyTags/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip48ProxyTags/ProxyTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip48ProxyTags/ProxyTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip48ProxyTags/ProxyTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip48ProxyTags/ProxyTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip48ProxyTags/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip48ProxyTags/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip48ProxyTags/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip48ProxyTags/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip48ProxyTags/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip48ProxyTags/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip48ProxyTags/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip48ProxyTags/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip49PrivKeyEnc/ByteArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip49PrivKeyEnc/ByteArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip49PrivKeyEnc/ByteArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip49PrivKeyEnc/ByteArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip49PrivKeyEnc/Nip49.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip49PrivKeyEnc/Nip49.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip49PrivKeyEnc/Nip49.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip49PrivKeyEnc/Nip49.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip49PrivKeyEnc/PBKDF.java b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip49PrivKeyEnc/PBKDF.java similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip49PrivKeyEnc/PBKDF.java rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip49PrivKeyEnc/PBKDF.java diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip49PrivKeyEnc/SCrypt.java b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip49PrivKeyEnc/SCrypt.java similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip49PrivKeyEnc/SCrypt.java rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip49PrivKeyEnc/SCrypt.java diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip49PrivKeyEnc/SecretKeyOrEmptySpec.java b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip49PrivKeyEnc/SecretKeyOrEmptySpec.java similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip49PrivKeyEnc/SecretKeyOrEmptySpec.java rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip49PrivKeyEnc/SecretKeyOrEmptySpec.java diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip50Search/SearchRelayListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip50Search/SearchRelayListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip50Search/SearchRelayListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip50Search/SearchRelayListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip50Search/SearchableEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip50Search/SearchableEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip50Search/SearchableEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip50Search/SearchableEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/PinListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/PinListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/PinListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/PinListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/PrivateTagArrayBuilder.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/PrivateTagArrayBuilder.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/PrivateTagArrayBuilder.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/PrivateTagArrayBuilder.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/PrivateTagArrayEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/PrivateTagArrayEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/PrivateTagArrayEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/PrivateTagArrayEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/PrivateTagArrayEventCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/PrivateTagArrayEventCache.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/PrivateTagArrayEventCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/PrivateTagArrayEventCache.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/bookmarkList/BookmarkListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/bookmarkList/BookmarkListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/bookmarkList/BookmarkListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/bookmarkList/BookmarkListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/bookmarkList/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/bookmarkList/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/bookmarkList/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/bookmarkList/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/bookmarkList/tags/AddressBookmark.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/bookmarkList/tags/AddressBookmark.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/bookmarkList/tags/AddressBookmark.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/bookmarkList/tags/AddressBookmark.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/bookmarkList/tags/BookmarkIdTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/bookmarkList/tags/BookmarkIdTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/bookmarkList/tags/BookmarkIdTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/bookmarkList/tags/BookmarkIdTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/bookmarkList/tags/EventBookmark.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/bookmarkList/tags/EventBookmark.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/bookmarkList/tags/EventBookmark.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/bookmarkList/tags/EventBookmark.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/encryption/NostrSignerExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/encryption/NostrSignerExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/encryption/NostrSignerExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/encryption/NostrSignerExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/encryption/PrivateTagsInContent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/encryption/PrivateTagsInContent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/encryption/PrivateTagsInContent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/encryption/PrivateTagsInContent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/followList/FollowListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/followList/FollowListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/followList/FollowListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/followList/FollowListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/followList/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/followList/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/followList/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/followList/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/followList/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/followList/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/followList/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/followList/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/geohashList/GeohashListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/geohashList/GeohashListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/geohashList/GeohashListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/geohashList/GeohashListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/geohashList/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/geohashList/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/geohashList/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/geohashList/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/geohashList/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/geohashList/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/geohashList/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/geohashList/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/hashtagList/HashtagListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/hashtagList/HashtagListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/hashtagList/HashtagListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/hashtagList/HashtagListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/hashtagList/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/hashtagList/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/hashtagList/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/hashtagList/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/hashtagList/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/hashtagList/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/hashtagList/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/hashtagList/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/muteList/MuteListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/muteList/MuteListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/muteList/MuteListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/muteList/MuteListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/muteList/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/muteList/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/muteList/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/muteList/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/muteList/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/muteList/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/muteList/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/muteList/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/muteList/tags/MuteTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/muteList/tags/MuteTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/muteList/tags/MuteTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/muteList/tags/MuteTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/muteList/tags/UserTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/muteList/tags/UserTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/muteList/tags/UserTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/muteList/tags/UserTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/muteList/tags/WordTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/muteList/tags/WordTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/muteList/tags/WordTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/muteList/tags/WordTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/peopleList/PeopleListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/peopleList/PeopleListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/peopleList/PeopleListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/peopleList/PeopleListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/peopleList/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/peopleList/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/peopleList/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/peopleList/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/peopleList/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/peopleList/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/peopleList/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/peopleList/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/BlockedRelayListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/BlockedRelayListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/BlockedRelayListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/BlockedRelayListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/BroadcastRelayListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/BroadcastRelayListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/BroadcastRelayListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/BroadcastRelayListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/IndexerRelayListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/IndexerRelayListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/IndexerRelayListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/IndexerRelayListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/ProxyRelayListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/ProxyRelayListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/ProxyRelayListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/ProxyRelayListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/TrustedRelayListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/TrustedRelayListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/TrustedRelayListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/TrustedRelayListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/tags/RelayTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/tags/RelayTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/tags/RelayTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/tags/RelayTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/tags/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/tags/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/tags/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/tags/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/tags/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/tags/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relayLists/tags/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relayLists/tags/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relaySets/RelaySetEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relaySets/RelaySetEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/relaySets/RelaySetEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/relaySets/RelaySetEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/tags/DescriptionTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/tags/DescriptionTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/tags/DescriptionTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/tags/DescriptionTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/tags/ImageTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/tags/ImageTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/tags/ImageTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/tags/ImageTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/tags/NameTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/tags/NameTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/tags/NameTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/tags/NameTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/tags/RelayTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/tags/RelayTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/tags/RelayTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/tags/RelayTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/tags/TitleTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/tags/TitleTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/tags/TitleTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip51Lists/tags/TitleTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip52Calendar/CalendarDateSlotEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip52Calendar/CalendarDateSlotEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip52Calendar/CalendarDateSlotEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip52Calendar/CalendarDateSlotEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip52Calendar/CalendarEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip52Calendar/CalendarEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip52Calendar/CalendarEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip52Calendar/CalendarEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip52Calendar/CalendarRSVPEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip52Calendar/CalendarRSVPEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip52Calendar/CalendarRSVPEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip52Calendar/CalendarRSVPEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip52Calendar/CalendarTimeSlotEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip52Calendar/CalendarTimeSlotEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip52Calendar/CalendarTimeSlotEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip52Calendar/CalendarTimeSlotEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/chat/LiveActivitiesChatMessageEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/chat/LiveActivitiesChatMessageEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/chat/LiveActivitiesChatMessageEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/chat/LiveActivitiesChatMessageEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/chat/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/chat/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/chat/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/chat/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/LiveActivitiesEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/LiveActivitiesEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/LiveActivitiesEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/LiveActivitiesEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/CurrentParticipantsTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/CurrentParticipantsTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/CurrentParticipantsTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/CurrentParticipantsTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/EndsTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/EndsTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/EndsTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/EndsTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/ParticipantTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/ParticipantTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/ParticipantTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/ParticipantTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/RelayListTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/RelayListTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/RelayListTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/RelayListTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StartsTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StartsTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StartsTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StartsTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StatusTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StatusTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StatusTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StatusTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StreamingTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StreamingTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StreamingTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StreamingTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/TotalParticipantsTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/TotalParticipantsTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/TotalParticipantsTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/TotalParticipantsTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip54Wiki/WikiNoteEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip54Wiki/WikiNoteEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip54Wiki/WikiNoteEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip54Wiki/WikiNoteEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/SignString.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/SignString.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/SignString.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/SignString.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/CommandType.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/CommandType.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/CommandType.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/CommandType.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/SignerResult.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/SignerResult.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/SignerResult.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/SignerResult.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/DecryptZapQuery.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/DecryptZapQuery.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/DecryptZapQuery.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/DecryptZapQuery.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/DeriveKeyQuery.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/DeriveKeyQuery.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/DeriveKeyQuery.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/DeriveKeyQuery.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/LoginQuery.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/LoginQuery.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/LoginQuery.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/LoginQuery.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip04DecryptQuery.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip04DecryptQuery.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip04DecryptQuery.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip04DecryptQuery.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip04EncryptQuery.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip04EncryptQuery.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip04EncryptQuery.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip04EncryptQuery.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip44DecryptQuery.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip44DecryptQuery.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip44DecryptQuery.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip44DecryptQuery.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip44EncryptQuery.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip44EncryptQuery.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip44EncryptQuery.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/Nip44EncryptQuery.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/SignQuery.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/SignQuery.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/SignQuery.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/queries/SignQuery.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/utils/ContentResolverExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/utils/ContentResolverExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/utils/ContentResolverExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/utils/ContentResolverExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/utils/CursorExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/utils/CursorExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/utils/CursorExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/background/utils/CursorExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/IntentRequestManager.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/IntentRequestManager.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/IntentRequestManager.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/IntentRequestManager.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/DecryptZapRequest.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/DecryptZapRequest.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/DecryptZapRequest.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/DecryptZapRequest.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/DeriveKeyRequest.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/DeriveKeyRequest.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/DeriveKeyRequest.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/DeriveKeyRequest.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/LoginRequest.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/LoginRequest.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/LoginRequest.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/LoginRequest.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip04DecryptRequest.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip04DecryptRequest.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip04DecryptRequest.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip04DecryptRequest.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip04EncryptRequest.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip04EncryptRequest.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip04EncryptRequest.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip04EncryptRequest.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip44DecryptRequest.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip44DecryptRequest.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip44DecryptRequest.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip44DecryptRequest.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip44EncryptRequest.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip44EncryptRequest.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip44EncryptRequest.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/Nip44EncryptRequest.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/SignRequest.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/SignRequest.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/SignRequest.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/requests/SignRequest.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/DecryptZapResponse.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/DecryptZapResponse.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/DecryptZapResponse.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/DecryptZapResponse.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/DeriveKeyResponse.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/DeriveKeyResponse.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/DeriveKeyResponse.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/DeriveKeyResponse.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/LoginResponse.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/LoginResponse.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/LoginResponse.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/LoginResponse.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip04DecryptResponse.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip04DecryptResponse.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip04DecryptResponse.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip04DecryptResponse.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip04EncryptResponse.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip04EncryptResponse.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip04EncryptResponse.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip04EncryptResponse.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip44DecryptResponse.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip44DecryptResponse.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip44DecryptResponse.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip44DecryptResponse.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip44EncryptResponse.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip44EncryptResponse.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip44EncryptResponse.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/Nip44EncryptResponse.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/SignResponse.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/SignResponse.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/SignResponse.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/responses/SignResponse.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/results/IntentResult.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/results/IntentResult.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/results/IntentResult.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/results/IntentResult.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/results/IntentResultJsonDeserializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/results/IntentResultJsonDeserializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/results/IntentResultJsonDeserializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/results/IntentResultJsonDeserializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/results/IntentResultJsonSerializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/results/IntentResultJsonSerializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/results/IntentResultJsonSerializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/foreground/intents/results/IntentResultJsonSerializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/permission/Permission.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/permission/Permission.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/permission/Permission.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/permission/Permission.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/permission/PermissionDeserializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/permission/PermissionDeserializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/permission/PermissionDeserializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/permission/PermissionDeserializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/permission/PermissionSerializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/permission/PermissionSerializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/api/permission/PermissionSerializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/api/permission/PermissionSerializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/client/ExternalSignerLogin.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/client/ExternalSignerLogin.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/client/ExternalSignerLogin.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/client/ExternalSignerLogin.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/client/IActivityLauncher.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/client/IActivityLauncher.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/client/IActivityLauncher.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/client/IActivityLauncher.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/client/IsExternalSignerInstalled.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/client/IsExternalSignerInstalled.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/client/IsExternalSignerInstalled.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/client/IsExternalSignerInstalled.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/client/NostrSignerExternal.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/client/NostrSignerExternal.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/client/NostrSignerExternal.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/client/NostrSignerExternal.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/client/handlers/BackgroundRequestHandler.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/client/handlers/BackgroundRequestHandler.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/client/handlers/BackgroundRequestHandler.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/client/handlers/BackgroundRequestHandler.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/client/handlers/ForegroundRequestHandler.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/client/handlers/ForegroundRequestHandler.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip55AndroidSigner/client/handlers/ForegroundRequestHandler.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip55AndroidSigner/client/handlers/ForegroundRequestHandler.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/ReportEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/ReportEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/ReportEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/ReportEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/ReportType.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/ReportType.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/ReportType.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/ReportType.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/tags/BaseReportTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/tags/BaseReportTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/tags/BaseReportTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/tags/BaseReportTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/tags/DefaultReportTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/tags/DefaultReportTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/tags/DefaultReportTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/tags/DefaultReportTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/tags/HashSha256Tag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/tags/HashSha256Tag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/tags/HashSha256Tag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/tags/HashSha256Tag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/tags/ReportedAddressTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/tags/ReportedAddressTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/tags/ReportedAddressTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/tags/ReportedAddressTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/tags/ReportedAuthorTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/tags/ReportedAuthorTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/tags/ReportedAuthorTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/tags/ReportedAuthorTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/tags/ReportedEventTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/tags/ReportedEventTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/tags/ReportedEventTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/tags/ReportedEventTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/tags/ServerTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/tags/ServerTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip56Reports/tags/ServerTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip56Reports/tags/ServerTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapEventInterface.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapEventInterface.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapEventInterface.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapEventInterface.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapPrivateEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapPrivateEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapPrivateEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapPrivateEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/PrivateZapCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/PrivateZapCache.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/PrivateZapCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/PrivateZapCache.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/PrivateZapEncryption.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/PrivateZapEncryption.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/PrivateZapEncryption.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/PrivateZapEncryption.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/PrivateZapRequestBuilder.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/PrivateZapRequestBuilder.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/PrivateZapRequestBuilder.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/PrivateZapRequestBuilder.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/BaseZapSplitSetup.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/BaseZapSplitSetup.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/BaseZapSplitSetup.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/BaseZapSplitSetup.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetup.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetup.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetup.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetup.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetupLnAddress.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetupLnAddress.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetupLnAddress.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetupLnAddress.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetupParser.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetupParser.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetupParser.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetupParser.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetupSerializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetupSerializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetupSerializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/splits/ZapSplitSetupSerializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/zapraiser/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/zapraiser/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/zapraiser/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/zapraiser/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/zapraiser/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/zapraiser/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/zapraiser/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/zapraiser/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/zapraiser/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/zapraiser/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/zapraiser/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/zapraiser/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/zapraiser/ZapRaiserTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/zapraiser/ZapRaiserTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/zapraiser/ZapRaiserTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip57Zaps/zapraiser/ZapRaiserTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip58Badges/BadgeAwardEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip58Badges/BadgeAwardEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip58Badges/BadgeAwardEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip58Badges/BadgeAwardEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip58Badges/BadgeDefinitionEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip58Badges/BadgeDefinitionEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip58Badges/BadgeDefinitionEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip58Badges/BadgeDefinitionEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip58Badges/BadgeProfilesEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip58Badges/BadgeProfilesEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip58Badges/BadgeProfilesEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip58Badges/BadgeProfilesEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/HostStub.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/HostStub.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/HostStub.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/HostStub.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/WrappedEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/WrappedEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/WrappedEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/WrappedEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/rumors/Rumor.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/rumors/Rumor.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/rumors/Rumor.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/rumors/Rumor.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/rumors/RumorAssembler.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/rumors/RumorAssembler.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/rumors/RumorAssembler.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/rumors/RumorAssembler.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/rumors/RumorDeserializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/rumors/RumorDeserializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/rumors/RumorDeserializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/rumors/RumorDeserializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/rumors/RumorSerializer.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/rumors/RumorSerializer.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/rumors/RumorSerializer.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/rumors/RumorSerializer.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/seals/SealedRumorEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/seals/SealedRumorEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/seals/SealedRumorEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/seals/SealedRumorEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/wraps/GiftWrapEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/wraps/GiftWrapEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip59Giftwrap/wraps/GiftWrapEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/wraps/GiftWrapEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip62RequestToVanish/RequestToVanishEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip62RequestToVanish/RequestToVanishEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip62RequestToVanish/RequestToVanishEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip62RequestToVanish/RequestToVanishEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip62RequestToVanish/tags/RelayTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip62RequestToVanish/tags/RelayTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip62RequestToVanish/tags/RelayTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip62RequestToVanish/tags/RelayTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip62RequestToVanish/tags/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip62RequestToVanish/tags/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip62RequestToVanish/tags/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip62RequestToVanish/tags/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip62RequestToVanish/tags/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip62RequestToVanish/tags/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip62RequestToVanish/tags/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip62RequestToVanish/tags/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip65RelayList/AdvertisedRelayListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip65RelayList/AdvertisedRelayListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip65RelayList/AdvertisedRelayListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip65RelayList/AdvertisedRelayListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip65RelayList/RelayListRecommendationProcessor.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip65RelayList/RelayListRecommendationProcessor.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip65RelayList/RelayListRecommendationProcessor.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip65RelayList/RelayListRecommendationProcessor.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip65RelayList/tags/AdvertisedRelayInfoTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip65RelayList/tags/AdvertisedRelayInfoTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip65RelayList/tags/AdvertisedRelayInfoTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip65RelayList/tags/AdvertisedRelayInfoTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip68Picture/IMetaTagBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip68Picture/IMetaTagBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip68Picture/IMetaTagBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip68Picture/IMetaTagBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip68Picture/IMetaTagExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip68Picture/IMetaTagExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip68Picture/IMetaTagExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip68Picture/IMetaTagExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip68Picture/PictureEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip68Picture/PictureEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip68Picture/PictureEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip68Picture/PictureEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip68Picture/PictureMeta.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip68Picture/PictureMeta.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip68Picture/PictureMeta.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip68Picture/PictureMeta.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip68Picture/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip68Picture/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip68Picture/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip68Picture/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip68Picture/tags/LocationTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip68Picture/tags/LocationTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip68Picture/tags/LocationTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip68Picture/tags/LocationTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip68Picture/tags/UserAnnotationTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip68Picture/tags/UserAnnotationTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip68Picture/tags/UserAnnotationTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip68Picture/tags/UserAnnotationTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip70ProtectedEvts/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip70ProtectedEvts/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip70ProtectedEvts/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip70ProtectedEvts/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip70ProtectedEvts/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip70ProtectedEvts/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip70ProtectedEvts/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip70ProtectedEvts/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip70ProtectedEvts/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip70ProtectedEvts/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip70ProtectedEvts/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip70ProtectedEvts/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip70ProtectedEvts/tags/ProtectedTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip70ProtectedEvts/tags/ProtectedTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip70ProtectedEvts/tags/ProtectedTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip70ProtectedEvts/tags/ProtectedTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/IMetaTagBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/IMetaTagBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/IMetaTagBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/IMetaTagBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/IMetaTagExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/IMetaTagExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/IMetaTagExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/IMetaTagExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/VideoEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/VideoEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/VideoEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/VideoEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/VideoHorizontalEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/VideoHorizontalEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/VideoHorizontalEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/VideoHorizontalEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/VideoMeta.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/VideoMeta.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/VideoMeta.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/VideoMeta.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/VideoNormalEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/VideoNormalEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/VideoNormalEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/VideoNormalEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/VideoShortEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/VideoShortEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/VideoShortEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/VideoShortEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/VideoVerticalEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/VideoVerticalEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/VideoVerticalEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/VideoVerticalEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/DurationTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/tags/DurationTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/DurationTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/tags/DurationTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/SegmentTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/tags/SegmentTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/SegmentTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/tags/SegmentTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/TextTrackTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/tags/TextTrackTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/TextTrackTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip71Video/tags/TextTrackTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/approval/CommunityPostApprovalEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/approval/CommunityPostApprovalEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/approval/CommunityPostApprovalEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/approval/CommunityPostApprovalEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/approval/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/approval/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/approval/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/approval/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/approval/tags/ApprovedAddressTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/approval/tags/ApprovedAddressTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/approval/tags/ApprovedAddressTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/approval/tags/ApprovedAddressTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/approval/tags/ApprovedEventTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/approval/tags/ApprovedEventTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/approval/tags/ApprovedEventTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/approval/tags/ApprovedEventTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/CommunityDefinitionEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/CommunityDefinitionEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/CommunityDefinitionEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/CommunityDefinitionEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/DescriptionTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/DescriptionTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/DescriptionTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/DescriptionTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ImageTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ImageTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ImageTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ImageTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ModeratorTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ModeratorTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ModeratorTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ModeratorTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/NameTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/NameTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/NameTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/NameTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RelayTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RelayTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RelayTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RelayTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RulesTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RulesTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RulesTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RulesTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/follow/CommunityListEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/follow/CommunityListEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/follow/CommunityListEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/follow/CommunityListEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/follow/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/follow/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/follow/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/follow/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/follow/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/follow/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/follow/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/follow/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/follow/tags/CommunityTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/follow/tags/CommunityTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/follow/tags/CommunityTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip72ModCommunities/follow/tags/CommunityTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/CommentEventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/CommentEventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/CommentEventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/CommentEventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/ExternalId.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/ExternalId.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/ExternalId.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/ExternalId.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/books/BookId.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/books/BookId.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/books/BookId.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/books/BookId.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/books/CommentEventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/books/CommentEventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/books/CommentEventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/books/CommentEventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/location/CommentEventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/location/CommentEventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/location/CommentEventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/location/CommentEventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/location/GeohashId.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/location/GeohashId.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/location/GeohashId.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/location/GeohashId.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/movies/CommentEventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/movies/CommentEventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/movies/CommentEventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/movies/CommentEventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/movies/MovieId.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/movies/MovieId.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/movies/MovieId.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/movies/MovieId.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/papers/CommentEventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/papers/CommentEventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/papers/CommentEventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/papers/CommentEventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/papers/PaperId.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/papers/PaperId.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/papers/PaperId.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/papers/PaperId.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/CommentEventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/CommentEventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/CommentEventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/CommentEventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/PodcastEpisodeId.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/PodcastEpisodeId.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/PodcastEpisodeId.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/PodcastEpisodeId.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/PodcastFeedId.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/PodcastFeedId.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/PodcastFeedId.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/PodcastFeedId.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/PodcastPublisherId.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/PodcastPublisherId.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/PodcastPublisherId.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/podcasts/PodcastPublisherId.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/topics/CommentEventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/topics/CommentEventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/topics/CommentEventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/topics/CommentEventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/topics/HashtagId.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/topics/HashtagId.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/topics/HashtagId.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/topics/HashtagId.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/urls/CommentEventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/urls/CommentEventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/urls/CommentEventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/urls/CommentEventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/urls/UrlId.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/urls/UrlId.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip73ExternalIds/urls/UrlId.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip73ExternalIds/urls/UrlId.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/GoalEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip75ZapGoals/GoalEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/GoalEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip75ZapGoals/GoalEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip75ZapGoals/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip75ZapGoals/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/AmountTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip75ZapGoals/tags/AmountTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/AmountTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip75ZapGoals/tags/AmountTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/ClosedAtTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip75ZapGoals/tags/ClosedAtTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/ClosedAtTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip75ZapGoals/tags/ClosedAtTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/RelayListTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip75ZapGoals/tags/RelayListTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/RelayListTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip75ZapGoals/tags/RelayListTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip78AppData/AppSpecificDataEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip78AppData/AppSpecificDataEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip78AppData/AppSpecificDataEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip78AppData/AppSpecificDataEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip84Highlights/HighlightEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip84Highlights/HighlightEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip84Highlights/HighlightEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip84Highlights/HighlightEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip84Highlights/tags/CommentTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip84Highlights/tags/CommentTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip84Highlights/tags/CommentTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip84Highlights/tags/CommentTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip84Highlights/tags/ContextTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip84Highlights/tags/ContextTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip84Highlights/tags/ContextTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip84Highlights/tags/ContextTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/PlatformType.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/PlatformType.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/PlatformType.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/PlatformType.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/ClientTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/ClientTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/ClientTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/ClientTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/definition/AppDefinitionEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/definition/AppDefinitionEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/definition/AppDefinitionEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/definition/AppDefinitionEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/definition/AppMetadata.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/definition/AppMetadata.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/definition/AppMetadata.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/definition/AppMetadata.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/definition/EntityType.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/definition/EntityType.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/definition/EntityType.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/definition/EntityType.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/definition/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/definition/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/definition/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/definition/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/definition/tags/PlatformLinkTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/definition/tags/PlatformLinkTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/definition/tags/PlatformLinkTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/definition/tags/PlatformLinkTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/AppRecommendationEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/AppRecommendationEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/AppRecommendationEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/AppRecommendationEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/tags/RecommendationTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/tags/RecommendationTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/tags/RecommendationTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/tags/RecommendationTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip90Dvms/NIP90ContentDiscoveryRequestEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip90Dvms/NIP90ContentDiscoveryRequestEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip90Dvms/NIP90ContentDiscoveryRequestEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip90Dvms/NIP90ContentDiscoveryRequestEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip90Dvms/NIP90ContentDiscoveryResponseEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip90Dvms/NIP90ContentDiscoveryResponseEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip90Dvms/NIP90ContentDiscoveryResponseEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip90Dvms/NIP90ContentDiscoveryResponseEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip90Dvms/NIP90StatusEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip90Dvms/NIP90StatusEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip90Dvms/NIP90StatusEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip90Dvms/NIP90StatusEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip90Dvms/NIP90UserDiscoveryRequestEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip90Dvms/NIP90UserDiscoveryRequestEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip90Dvms/NIP90UserDiscoveryRequestEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip90Dvms/NIP90UserDiscoveryRequestEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip90Dvms/NIP90UserDiscoveryResponseEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip90Dvms/NIP90UserDiscoveryResponseEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip90Dvms/NIP90UserDiscoveryResponseEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip90Dvms/NIP90UserDiscoveryResponseEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip92IMeta/EventExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip92IMeta/EventExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip92IMeta/EventExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip92IMeta/EventExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip92IMeta/IMetaTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip92IMeta/IMetaTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip92IMeta/IMetaTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip92IMeta/IMetaTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip92IMeta/IMetaTagBuilder.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip92IMeta/IMetaTagBuilder.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip92IMeta/IMetaTagBuilder.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip92IMeta/IMetaTagBuilder.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip92IMeta/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip92IMeta/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip92IMeta/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip92IMeta/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip92IMeta/TagArrayExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip92IMeta/TagArrayExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip92IMeta/TagArrayExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip92IMeta/TagArrayExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/FileHeaderEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/FileHeaderEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/FileHeaderEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/FileHeaderEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/IMetaTagBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/IMetaTagBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/IMetaTagBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/IMetaTagBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/BlurhashTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/BlurhashTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/BlurhashTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/BlurhashTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/DimensionTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/DimensionTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/DimensionTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/DimensionTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/FallbackTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/FallbackTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/FallbackTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/FallbackTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/HashSha256Tag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/HashSha256Tag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/HashSha256Tag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/HashSha256Tag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ImageTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/ImageTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ImageTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/ImageTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/MagnetTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/MagnetTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/MagnetTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/MagnetTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/MimeTypeTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/MimeTypeTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/MimeTypeTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/MimeTypeTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/OriginalHashTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/OriginalHashTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/OriginalHashTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/OriginalHashTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ServiceTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/ServiceTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ServiceTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/ServiceTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/SizeTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/SizeTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/SizeTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/SizeTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/SummaryTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/SummaryTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/SummaryTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/SummaryTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ThumbTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/ThumbTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ThumbTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/ThumbTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/TorrentInfoHash.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/TorrentInfoHash.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/TorrentInfoHash.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/TorrentInfoHash.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/UrlTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/UrlTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/UrlTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip94FileMetadata/tags/UrlTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/HttpUrlFormatter.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/HttpUrlFormatter.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/HttpUrlFormatter.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/HttpUrlFormatter.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/actions/DeleteResult.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/actions/DeleteResult.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/actions/DeleteResult.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/actions/DeleteResult.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/actions/UploadResult.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/actions/UploadResult.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/actions/UploadResult.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/actions/UploadResult.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/config/FileServersEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/config/FileServersEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/config/FileServersEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/config/FileServersEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/config/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/config/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/config/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/config/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/config/tags/ServerTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/config/tags/ServerTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/config/tags/ServerTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/config/tags/ServerTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/info/ServerInfo.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/info/ServerInfo.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/info/ServerInfo.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/info/ServerInfo.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/info/ServerInfoParser.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/info/ServerInfoParser.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/info/ServerInfoParser.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip96FileStorage/info/ServerInfoParser.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/HTTPAuthorizationEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip98HttpAuth/HTTPAuthorizationEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/HTTPAuthorizationEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip98HttpAuth/HTTPAuthorizationEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip98HttpAuth/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip98HttpAuth/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/MethodTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip98HttpAuth/tags/MethodTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/MethodTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip98HttpAuth/tags/MethodTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/PayloadHashTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip98HttpAuth/tags/PayloadHashTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/PayloadHashTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip98HttpAuth/tags/PayloadHashTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/UrlTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip98HttpAuth/tags/UrlTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/UrlTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip98HttpAuth/tags/UrlTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/ClassifiedsEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip99Classifieds/ClassifiedsEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/ClassifiedsEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip99Classifieds/ClassifiedsEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/ProductImageMeta.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip99Classifieds/ProductImageMeta.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/ProductImageMeta.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip99Classifieds/ProductImageMeta.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip99Classifieds/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip99Classifieds/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/ConditionTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip99Classifieds/tags/ConditionTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/ConditionTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip99Classifieds/tags/ConditionTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/LocationTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip99Classifieds/tags/LocationTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/LocationTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip99Classifieds/tags/LocationTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/PriceTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip99Classifieds/tags/PriceTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/PriceTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip99Classifieds/tags/PriceTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/StatusTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip99Classifieds/tags/StatusTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/StatusTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nip99Classifieds/tags/StatusTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/AudioMeta.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/AudioMeta.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/AudioMeta.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/AudioMeta.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/BaseVoiceEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/BaseVoiceEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/BaseVoiceEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/BaseVoiceEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/IMetaTagBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/IMetaTagBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/IMetaTagBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/IMetaTagBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/IMetaTagExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/IMetaTagExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/IMetaTagExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/IMetaTagExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/TagArrayBuilderExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/TagArrayBuilderExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/TagArrayBuilderExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/TagArrayBuilderExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/VoiceEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/VoiceEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/VoiceEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/VoiceEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/VoiceReplyEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/VoiceReplyEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/VoiceReplyEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/VoiceReplyEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/DurationTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/DurationTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/DurationTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/DurationTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/HashSha256Tag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/HashSha256Tag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/HashSha256Tag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/HashSha256Tag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/MimeTypeTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/MimeTypeTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/MimeTypeTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/MimeTypeTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/ReplyAuthorTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/ReplyAuthorTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/ReplyAuthorTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/ReplyAuthorTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/ReplyEventTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/ReplyEventTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/ReplyEventTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/ReplyEventTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/ReplyKindTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/ReplyKindTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/ReplyKindTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/ReplyKindTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/WaveformTag.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/WaveformTag.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/WaveformTag.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipA0VoiceMessages/tags/WaveformTag.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipB7Blossom/BlossomAuthorizationEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipB7Blossom/BlossomAuthorizationEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipB7Blossom/BlossomAuthorizationEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipB7Blossom/BlossomAuthorizationEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nipB7Blossom/BlossomServersEvent.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipB7Blossom/BlossomServersEvent.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/nipB7Blossom/BlossomServersEvent.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/nipB7Blossom/BlossomServersEvent.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/ArrayUtils.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/ArrayUtils.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/ArrayUtils.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/ArrayUtils.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/CacheCollectors.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/CacheCollectors.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/CacheCollectors.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/CacheCollectors.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/CacheOperations.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/CacheOperations.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/CacheOperations.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/CacheOperations.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/Ensure.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/Ensure.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/Ensure.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/Ensure.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/GZip.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/GZip.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/GZip.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/GZip.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/Hex.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/Hex.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/Hex.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/Hex.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/Hmac512.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/Hmac512.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/Hmac512.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/Hmac512.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/IterableExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/IterableExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/IterableExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/IterableExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/LargeCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/LargeCache.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/LargeCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/LargeCache.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/LargeSoftCache.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/LargeSoftCache.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/LargeSoftCache.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/LargeSoftCache.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/LibSodiumInstance.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/LibSodiumInstance.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/LibSodiumInstance.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/LibSodiumInstance.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/MapOfSetBuilder.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/MapOfSetBuilder.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/MapOfSetBuilder.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/MapOfSetBuilder.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/ParallelUtils.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/ParallelUtils.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/ParallelUtils.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/ParallelUtils.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/RandomInstance.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/RandomInstance.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/RandomInstance.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/RandomInstance.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/Secp256k1Instance.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/Secp256k1Instance.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/Secp256k1Instance.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/Secp256k1Instance.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/StringUtils.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/StringUtils.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/StringUtils.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/StringUtils.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/TimeUtils.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/TimeUtils.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/TimeUtils.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/TimeUtils.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/UriReferenceExt.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/UriReferenceExt.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/UriReferenceExt.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/UriReferenceExt.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/sha256/Sha256.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/sha256/Sha256.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/sha256/Sha256.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/sha256/Sha256.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/sha256/Sha256Hasher.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/sha256/Sha256Hasher.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/sha256/Sha256Hasher.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/sha256/Sha256Hasher.kt diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/utils/sha256/Sha256Pool.kt b/quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/sha256/Sha256Pool.kt similarity index 100% rename from quartz/src/main/java/com/vitorpamplona/quartz/utils/sha256/Sha256Pool.kt rename to quartz/src/androidMain/kotlin/com/vitorpamplona/quartz/utils/sha256/Sha256Pool.kt diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/Platform.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/Platform.kt new file mode 100644 index 000000000..efd8e787c --- /dev/null +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/Platform.kt @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2025 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 + +expect fun platform(): String diff --git a/quartz/src/iosMain/kotlin/com/vitorpamplona/quartz/Platform.ios.kt b/quartz/src/iosMain/kotlin/com/vitorpamplona/quartz/Platform.ios.kt new file mode 100644 index 000000000..60e069e46 --- /dev/null +++ b/quartz/src/iosMain/kotlin/com/vitorpamplona/quartz/Platform.ios.kt @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2025 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 + +actual fun platform() = "iOS" diff --git a/quartz/src/main/AndroidManifest.xml b/quartz/src/main/AndroidManifest.xml deleted file mode 100644 index 44008a433..000000000 --- a/quartz/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/BitcoinExplorer.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/BitcoinExplorer.java deleted file mode 100644 index 37a7de152..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/BitcoinExplorer.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -public interface BitcoinExplorer { - /** - * Retrieve the block information from the block hash. - * - * @param hash Hash of the block. - * @return the blockheader of the hash - * @throws Exception desc - */ - public BlockHeader block(final String hash) throws Exception; - - /** - * Retrieve the block hash from the block height. - * - * @param height Height of the block. - * @return the hash of the block at height height - * @throws Exception desc - */ - public String blockHash(final Integer height) throws Exception; -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/BlockHeader.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/BlockHeader.java deleted file mode 100644 index c13deba43..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/BlockHeader.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -public class BlockHeader { - - private String merkleroot; - private String blockHash; - private String time; - - public void setTime(String time) { - this.time = time; - } - - public Long getTime() { - return Long.valueOf(time); - } - - public String getMerkleroot() { - return merkleroot; - } - - public void setMerkleroot(String merkleroot) { - this.merkleroot = merkleroot; - } - - public String getBlockHash() { - return blockHash; - } - - public void setBlockHash(String blockHash) { - this.blockHash = blockHash; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - BlockHeader that = (BlockHeader) o; - - if (merkleroot != null ? !merkleroot.equals(that.merkleroot) : that.merkleroot != null) { - return false; - } - - if (blockHash != null ? !blockHash.equals(that.blockHash) : that.blockHash != null) { - return false; - } - - return time != null ? time.equals(that.time) : that.time == null; - } - - @Override - public int hashCode() { - int result = merkleroot != null ? merkleroot.hashCode() : 0; - result = 31 * result + (blockHash != null ? blockHash.hashCode() : 0); - result = 31 * result + (time != null ? time.hashCode() : 0); - - return result; - } - - @Override - public String toString() { - return "BlockHeader{" + - "merkleroot='" + merkleroot + '\'' + - ", blockHash='" + blockHash + '\'' + - ", time='" + time + '\'' + - '}'; - } -} \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/BlockstreamExplorer.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/BlockstreamExplorer.java deleted file mode 100644 index d08821446..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/BlockstreamExplorer.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -import android.util.Log; - -import com.fasterxml.jackson.databind.JsonNode; -import com.vitorpamplona.quartz.nip03Timestamp.ots.http.Request; -import com.vitorpamplona.quartz.nip03Timestamp.ots.http.Response; - -import java.net.URL; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -public class BlockstreamExplorer implements BitcoinExplorer { - private static final String esploraUrl = "https://blockstream.info/api"; - - /** - * Retrieve the block information from the block hash. - * - * @param hash Hash of the block. - * @return the blockheader of the hash - * @throws Exception desc - */ - public BlockHeader block(final String hash) throws Exception { - final URL url = new URL(esploraUrl + "/block/" + hash); - final Request task = new Request(url); - final ExecutorService executor = Executors.newSingleThreadExecutor(); - final Future future = executor.submit(task); - final Response take = future.get(); - executor.shutdown(); - if (!take.isOk()) - throw new Exception(); - - final JsonNode jsonObject = take.getJson(); - final String merkleroot = jsonObject.get("merkle_root").asText(); - final String time = String.valueOf(jsonObject.get("timestamp").asInt()); - final BlockHeader blockHeader = new BlockHeader(); - blockHeader.setMerkleroot(merkleroot); - blockHeader.setTime(time); - blockHeader.setBlockHash(hash); - Log.i("BlockstreamExplorer", take.getFromUrl() + " " + blockHeader); - return blockHeader; - //log.warning("Cannot parse merkleroot from body: " + jsonObject + ": " + e.getMessage()); - } - - /** - * Retrieve the block hash from the block height. - * - * @param height Height of the block. - * @return the hash of the block at height height - * @throws Exception desc - */ - public String blockHash(final Integer height) throws Exception { - final URL url = new URL(esploraUrl + "/block-height/" + height); - final Request task = new Request(url); - final ExecutorService executor = Executors.newSingleThreadExecutor(); - final Future future = executor.submit(task); - final Response take = future.get(); - executor.shutdown(); - if (!take.isOk()) - throw new Exception(); - final String blockHash = take.getString(); - Log.i("BlockstreamExplorer", take.getFromUrl() + " " + blockHash); - return blockHash; - } -} \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Calendar.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Calendar.java deleted file mode 100644 index 49fc52f8b..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Calendar.java +++ /dev/null @@ -1,123 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.CommitmentNotFoundException; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.ExceededSizeException; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.UrlException; -import com.vitorpamplona.quartz.nip03Timestamp.ots.http.Request; -import com.vitorpamplona.quartz.nip03Timestamp.ots.http.Response; - -import java.net.URL; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -/** - * Class representing remote calendar server interface. - */ -public class Calendar implements ICalendar { - - private String url; - - - /** - * Create a RemoteCalendar. - * - * @param url The server url. - */ - public Calendar(String url) { - this.url = url; - } - - /** - * Get calendar url. - * - * @return The calendar url. - */ - public String getUrl() { - return this.url; - } - - /** - * Submitting a digest to remote calendar. Returns a com.eternitywall.ots.Timestamp committing to that digest. - * - * @param digest The digest hash to send. - * @return the Timestamp received from the calendar. - * @throws ExceededSizeException if response is too big. - * @throws UrlException if url is not reachable. - * @throws DeserializationException if the data is corrupt - */ - @Override - public Timestamp submit(byte[] digest) - throws ExceededSizeException, UrlException, DeserializationException { - try { - Map headers = new HashMap<>(); - headers.put("Accept", "application/vnd.opentimestamps.v1"); - headers.put("User-Agent", "java-opentimestamps"); - headers.put("Content-Type", "application/x-www-form-urlencoded"); - - URL obj = new URL(url + "/digest"); - Request task = new Request(obj); - task.setData(digest); - task.setHeaders(headers); - Response response = task.call(); - byte[] body = response.getBytes(); - if (body.length > 10000) { - throw new ExceededSizeException("Calendar response exceeded size limit"); - } - - StreamDeserializationContext ctx = new StreamDeserializationContext(body); - return Timestamp.deserialize(ctx, digest); - } catch (ExceededSizeException | DeserializationException e) - { - throw e; - } - catch (Exception e) { - throw new UrlException(e.getMessage()); - } - } - - /** - * Get a timestamp for a given commitment. - * - * @param commitment The digest hash to send. - * @return the Timestamp from the calendar server (with blockchain information if already written). - * @throws ExceededSizeException if response is too big. - * @throws UrlException if url is not reachable. - * @throws CommitmentNotFoundException if commit is not found. - * @throws DeserializationException if the data is corrupt - */ - @Override - public Timestamp getTimestamp(byte[] commitment) throws DeserializationException, ExceededSizeException, CommitmentNotFoundException, UrlException { - try { - Map headers = new HashMap<>(); - headers.put("Accept", "application/vnd.opentimestamps.v1"); - headers.put("User-Agent", "java-opentimestamps"); - headers.put("Content-Type", "application/x-www-form-urlencoded"); - - URL obj = new URL(url + "/timestamp/" + Utils.bytesToHex(commitment).toLowerCase(Locale.ROOT)); - Request task = new Request(obj); - task.setHeaders(headers); - Response response = task.call(); - byte[] body = response.getBytes(); - if (body.length > 10000) { - throw new ExceededSizeException("Calendar response exceeded size limit"); - } - - if (!response.isOk()) { - throw new CommitmentNotFoundException("com.eternitywall.ots.Calendar response a status code != 200 which is: " + response.getStatus()); - } - - StreamDeserializationContext ctx = new StreamDeserializationContext(body); - - return Timestamp.deserialize(ctx, commitment); - } - catch (DeserializationException | ExceededSizeException | CommitmentNotFoundException e) - { - throw e; - } - catch (Exception e) { - throw new UrlException(e.getMessage()); - } - } -} \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarAsyncSubmit.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarAsyncSubmit.java deleted file mode 100644 index e6b84a00f..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarAsyncSubmit.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.http.Request; -import com.vitorpamplona.quartz.nip03Timestamp.ots.http.Response; - -import java.net.URL; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.BlockingQueue; - -/** - * For making async calls to a calendar server - */ -public class CalendarAsyncSubmit implements ICalendarAsyncSubmit { - - private String url; - private byte[] digest; - private BlockingQueue> queue; - - public CalendarAsyncSubmit(String url, byte[] digest) { - this.url = url; - this.digest = digest; - } - - public void setQueue(BlockingQueue> queue) { - this.queue = queue; - } - - @Override - public Optional call() throws Exception { - Map headers = new HashMap<>(); - headers.put("Accept", "application/vnd.opentimestamps.v1"); - headers.put("User-Agent", "java-opentimestamps"); - headers.put("Content-Type", "application/x-www-form-urlencoded"); - - URL obj = new URL(url + "/digest"); - Request task = new Request(obj); - task.setData(digest); - task.setHeaders(headers); - Response response = task.call(); - - if (response.isOk()) { - byte[] body = response.getBytes(); - StreamDeserializationContext ctx = new StreamDeserializationContext(body); - Timestamp timestamp = Timestamp.deserialize(ctx, digest); - Optional of = Optional.of(timestamp); - queue.add(of); - return of; - } - - queue.add(Optional.empty()); - - return Optional.empty(); - } -} \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarBuilder.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarBuilder.java deleted file mode 100644 index 1dd68ed8c..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarBuilder.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -public interface CalendarBuilder { - public ICalendar newSyncCalendar(String url); - public ICalendarAsyncSubmit newAsyncCalendar(String url, byte[] digest); -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarPureJavaBuilder.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarPureJavaBuilder.java deleted file mode 100644 index 85ff8b2c5..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/CalendarPureJavaBuilder.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -public class CalendarPureJavaBuilder implements CalendarBuilder { - public ICalendar newSyncCalendar(String url) { - return new Calendar(url); - } - public ICalendarAsyncSubmit newAsyncCalendar(String url, byte[] digest) { - return new CalendarAsyncSubmit(url, digest); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/DetachedTimestampFile.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/DetachedTimestampFile.java deleted file mode 100644 index 2bc8d50e0..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/DetachedTimestampFile.java +++ /dev/null @@ -1,227 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException; -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.Op; -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpCrypto; -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpSHA256; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.security.NoSuchAlgorithmException; - -/** - * Class representing Detached com.vitorpamplona.quartz.ots.Timestamp File. - * A file containing a timestamp for another file. - * Contains a timestamp, along with a header and the digest of the file. - */ -public class DetachedTimestampFile { - - /** - * Header magic bytes Designed to be give the user some information in a hexdump, while being - * identified as 'data' by the file utility. - * - * @default \x00OpenTimestamps\x00\x00Proof\x00\xbf\x89\xe2\xe8\x84\xe8\x92\x94 - */ - static byte[] HEADER_MAGIC = {(byte) 0x00, (byte) 0x4f, (byte) 0x70, (byte) 0x65, (byte) 0x6e, - (byte) 0x54, (byte) 0x69, (byte) 0x6d, (byte) 0x65, (byte) 0x73, - (byte) 0x74, (byte) 0x61, (byte) 0x6d, (byte) 0x70, (byte) 0x73, (byte) 0x00, (byte) 0x00, - (byte) 0x50, (byte) 0x72, (byte) 0x6f, (byte) 0x6f, (byte) 0x66, (byte) 0x00, - (byte) 0xbf, (byte) 0x89, (byte) 0xe2, (byte) 0xe8, (byte) 0x84, (byte) 0xe8, (byte) 0x92, - (byte) 0x94}; - - /** - * While the git commit timestamps have a minor version, probably better to - * leave it out here: unlike Git commits round-tripping is an issue when - * timestamps are upgraded, and we could end up with bugs related to not - * saving/updating minor version numbers correctly. - * - * @default 1 - */ - static byte MAJOR_VERSION = 1; - - Op fileHashOp; - Timestamp timestamp; - - public DetachedTimestampFile(Op fileHashOp, Timestamp timestamp) { - this.fileHashOp = fileHashOp; - this.timestamp = timestamp; - } - - /** - * The digest of the file that was timestamped. - * - * @return The message inside the timestamp. - */ - public byte[] fileDigest() { - return this.timestamp.msg; - } - - /** - * Retrieve the internal timestamp. - * - * @return the timestamp. - */ - public Timestamp getTimestamp() { - return this.timestamp; - } - - /** - * Serialize a com.vitorpamplona.quartz.ots.Timestamp File. - * - * @param ctx The stream serialization context. - */ - public void serialize(StreamSerializationContext ctx) { - ctx.writeBytes(HEADER_MAGIC); - ctx.writeVaruint(MAJOR_VERSION); - this.fileHashOp.serialize(ctx); - ctx.writeBytes(this.timestamp.msg); - this.timestamp.serialize(ctx); - } - - /** - * Serialize a com.vitorpamplona.quartz.ots.Timestamp File. - * - * @return The byte array of serialized data. - */ - public byte[] serialize() { - StreamSerializationContext ctx = new StreamSerializationContext(); - this.serialize(ctx); - - return ctx.getOutput(); - } - - /** - * Deserialize a com.vitorpamplona.quartz.ots.Timestamp File. - * - * @param ctx The stream deserialization context. - * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. - */ - public static DetachedTimestampFile deserialize(StreamDeserializationContext ctx) throws DeserializationException { - ctx.assertMagic(HEADER_MAGIC); - ctx.readVaruint(); - - OpCrypto fileHashOp = (OpCrypto) OpCrypto.deserialize(ctx); - byte[] fileHash = ctx.readBytes(fileHashOp._DIGEST_LENGTH()); - Timestamp timestamp = Timestamp.deserialize(ctx, fileHash); - - ctx.assertEof(); - - return new DetachedTimestampFile(fileHashOp, timestamp); - } - - /** - * Deserialize a com.vitorpamplona.quartz.ots.Timestamp File. - * - * @param ots The byte array of deserialization DetachedFileTimestamped. - * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. - */ - public static DetachedTimestampFile deserialize(byte[] ots) throws DeserializationException { - StreamDeserializationContext ctx = new StreamDeserializationContext(ots); - - return DetachedTimestampFile.deserialize(ctx); - } - - /** - * Read the Detached com.vitorpamplona.quartz.ots.Timestamp File from bytes. - * - * @param fileHashOp The file hash operation. - * @param ctx The stream deserialization context. - * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. - * @throws NoSuchAlgorithmException desc - */ - public static DetachedTimestampFile from(OpCrypto fileHashOp, StreamDeserializationContext ctx) throws NoSuchAlgorithmException { - byte[] fdHash = fileHashOp.hashFd(ctx); - - return new DetachedTimestampFile(fileHashOp, new Timestamp(fdHash)); - } - - /** - * Read the Detached com.vitorpamplona.quartz.ots.Timestamp File from bytes. - * - * @param fileHashOp The file hash operation. - * @param bytes The byte array of data to hash - * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. - * @throws NoSuchAlgorithmException desc - */ - public static DetachedTimestampFile from(OpCrypto fileHashOp, byte[] bytes) throws Exception { - byte[] fdHash = fileHashOp.hashFd(bytes); - - return new DetachedTimestampFile(fileHashOp, new Timestamp(fdHash)); - } - - /** - * Read the Detached com.vitorpamplona.quartz.ots.Timestamp File from hash. - * - * @param inputStream The InputStream of the file to hash - * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. - * @throws Exception if the input stream is null - */ - public static DetachedTimestampFile from(InputStream inputStream) throws Exception { - if (inputStream == null) { - throw new Exception(); // TODO: Add exception string later on - } - - try { - DetachedTimestampFile fileTimestamp = DetachedTimestampFile.from(new OpSHA256(), inputStream); // Read from file reader stream - return fileTimestamp; - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - throw new Exception(); - } - } - - /** - * Read the Detached com.vitorpamplona.quartz.ots.Timestamp File from InputStream. - * - * @param fileHashOp The file hash operation. - * @param inputStream The input stream file. - * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. - * @throws IOException desc - * @throws NoSuchAlgorithmException desc - */ - public static DetachedTimestampFile from(OpCrypto fileHashOp, InputStream inputStream) throws IOException, NoSuchAlgorithmException { - byte[] fdHash = fileHashOp.hashFd(inputStream); - - return new DetachedTimestampFile(fileHashOp, new Timestamp(fdHash)); - } - - /** - * Read the Detached com.vitorpamplona.quartz.ots.Timestamp File from hash. - * - * @param hash The hash of the file. - * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. - */ - public static DetachedTimestampFile from(Hash hash) { - return new DetachedTimestampFile(hash.getOp(), new Timestamp(hash.getValue())); - } - - /** - * Read the Detached com.vitorpamplona.quartz.ots.Timestamp File from File. - * - * @param fileHashOp The file hash operation. - * @param file The hash file. - * @return The generated com.vitorpamplona.quartz.ots.DetachedTimestampFile object. - * @throws IOException desc - * @throws NoSuchAlgorithmException desc - */ - public static DetachedTimestampFile from(OpCrypto fileHashOp, File file) throws IOException, NoSuchAlgorithmException { - byte[] fdHash = fileHashOp.hashFd(file); - - return new DetachedTimestampFile(fileHashOp, new Timestamp(fdHash)); - } - - /** - * Print the object. - * - * @return The output. - */ - @Override - public String toString() { - String output = "com.vitorpamplona.quartz.ots.DetachedTimestampFile\n"; - output += "fileHashOp: " + this.fileHashOp.toString() + '\n'; - output += "timestamp: " + this.timestamp.toString() + '\n'; - - return output; - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Hash.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Hash.java deleted file mode 100644 index 80d9f4223..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Hash.java +++ /dev/null @@ -1,202 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -import androidx.annotation.NonNull; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpCrypto; -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpKECCAK256; -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpRIPEMD160; -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpSHA1; -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpSHA256; -import com.vitorpamplona.quartz.utils.Hex; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.security.NoSuchAlgorithmException; -import java.util.Locale; - -public class Hash { - - private byte[] value; - private byte algorithm; - - /** - * Create a Hash object. - * - * @param value - The byte array of the hash - * @param algorithm - The hashlib tag of crypto operation - */ - public Hash(byte[] value, byte algorithm) { - this.value = value; - this.algorithm = algorithm; - } - - /** - * Create a Hash object. - * - * @param value - The byte array of the hash - * @param label - The hashlib name of crypto operation - */ - public Hash(byte[] value, String label) { - this.value = value; - this.algorithm = getOp(label)._TAG(); - } - - /** - * Get Value. - * - * @return value - The hash in byte array. - */ - public byte[] getValue() { - return value; - } - - /** - * Set Value tag. - * - * @param value - The hash in byte array. - */ - public void setValue(byte[] value) { - this.value = value; - } - - /** - * Get Algorithm tag. - * - * @return algorithm - The algorithm tag of crypto operation. - */ - public byte getAlgorithm() { - return algorithm; - } - - /** - * Set Algorithm tag. - * - * @param algorithm - The algorithm tag of crypto operation. - */ - public void setAlgorithm(byte algorithm) { - this.algorithm = algorithm; - } - - /** - * Get the current Crypto operation. - * - * @return The generated com.vitorpamplona.quartz.ots.OpCrypto object. - */ - public OpCrypto getOp() { - if (this.algorithm == OpSHA1._TAG) { - return new OpSHA1(); - } else if (this.algorithm == OpSHA256._TAG) { - return new OpSHA256(); - } else if (this.algorithm == OpRIPEMD160._TAG) { - return new OpRIPEMD160(); - } else if (this.algorithm == OpKECCAK256._TAG) { - return new OpKECCAK256(); - } - - return new OpSHA256(); - } - - /** - * Get Crypto operation from hashlib tag. - * - * @param algorithm The hashlib tag. - * @return The generated com.vitorpamplona.quartz.ots.OpCrypto object. - */ - public static OpCrypto getOp(byte algorithm) { - if (algorithm == OpSHA1._TAG) { - return new OpSHA1(); - } else if (algorithm == OpSHA256._TAG) { - return new OpSHA256(); - } else if (algorithm == OpRIPEMD160._TAG) { - return new OpRIPEMD160(); - } else if (algorithm == OpKECCAK256._TAG) { - return new OpKECCAK256(); - } - - return new OpSHA256(); - } - - /** - * Get Crypto operation from hashlib name. - * - * @param label The hashlib name. - * @return The generated com.vitorpamplona.quartz.ots.OpCrypto object. - */ - public static OpCrypto getOp(String label) { - if (label.toLowerCase(Locale.ROOT).equals(new OpSHA1()._TAG_NAME())) { - return new OpSHA1(); - } else if (label.toLowerCase(Locale.ROOT).equals(new OpSHA256()._TAG_NAME())) { - return new OpSHA256(); - } else if (label.toLowerCase(Locale.ROOT).equals(new OpRIPEMD160()._TAG_NAME())) { - return new OpRIPEMD160(); - } else if (label.toLowerCase(Locale.ROOT).equals(new OpKECCAK256()._TAG_NAME())) { - return new OpKECCAK256(); - } - - return new OpSHA256(); - } - - /** - * Build hash from data. - * - * @param bytes The byte array of data to hash. - * @param algorithm The hash file. - * @return The generated com.vitorpamplona.quartz.ots.Hash object. - * @throws IOException desc - * @throws NoSuchAlgorithmException desc - */ - public static Hash from(byte[] bytes, byte algorithm) throws IOException, NoSuchAlgorithmException { - OpCrypto opCrypto = getOp(algorithm); - byte[] value = opCrypto.hashFd(bytes); - - return new Hash(value, algorithm); - } - - /** - * Build hash from File. - * - * @param file The File of data to hash. - * @param algorithm The hash file. - * @return The generated com.vitorpamplona.quartz.ots.Hash object. - * @throws IOException desc - * @throws NoSuchAlgorithmException desc - */ - public static Hash from(File file, byte algorithm) throws IOException, NoSuchAlgorithmException { - OpCrypto opCrypto = getOp(algorithm); - byte[] value = opCrypto.hashFd(file); - - return new Hash(value, algorithm); - } - - /** - * Build hash from InputStream. - * - * @param inputStream The InputStream of data to hash. - * @param algorithm The hash file. - * @return The generated com.vitorpamplona.quartz.ots.Hash object. - * @throws IOException desc - * @throws NoSuchAlgorithmException desc - */ - public static Hash from(InputStream inputStream, byte algorithm) throws IOException, NoSuchAlgorithmException { - OpCrypto opCrypto = getOp(algorithm); - byte[] value = opCrypto.hashFd(inputStream); - - return new Hash(value, algorithm); - } - - /** - * Print the object. - * - * @return The output. - */ - @NonNull - @Override - public String toString() { - String output = "com.vitorpamplona.quartz.ots.Hash\n"; - output += "algorithm: " + this.getOp()._HASHLIB_NAME() + '\n'; - output += "value: " + Hex.encode(this.value) + '\n'; - - return output; - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendar.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendar.java deleted file mode 100644 index 75a546583..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendar.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.CommitmentNotFoundException; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.ExceededSizeException; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.UrlException; - -public interface ICalendar { - Timestamp submit(byte[] digest) - throws ExceededSizeException, UrlException, DeserializationException; - - Timestamp getTimestamp(byte[] commitment) throws DeserializationException, ExceededSizeException, CommitmentNotFoundException, UrlException; -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendarAsyncSubmit.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendarAsyncSubmit.java deleted file mode 100644 index 22e785c2b..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/ICalendarAsyncSubmit.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -import java.util.Optional; -import java.util.concurrent.Callable; - -public interface ICalendarAsyncSubmit extends Callable> { - @Override - Optional call() throws Exception; -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Merkle.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Merkle.java deleted file mode 100644 index df129fbab..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Merkle.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpAppend; -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpPrepend; -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpSHA256; - -import java.util.ArrayList; -import java.util.List; - -/** - * Utility functions for merkle trees - */ -public class Merkle { - - /** - * Concatenate left and right, then perform a unary operation on them left and right can be either timestamps or bytes. - * Appropriate intermediary append/prepend operations will be created as needed for left and right. - * - * @param left the left timestamp parameter - * @param right the right timestamp parameter - * @return the concatenation of left and right - */ - public static Timestamp catThenUnaryOp(Timestamp left, Timestamp right) { - // rightPrependStamp = right.ops.add(OpPrepend(left.msg)) - Timestamp rightPrependStamp = right.add(new OpPrepend(left.msg)); - - // Left and right should produce the same thing, so we can set the timestamp of the left to the right. - // left.ops[OpAppend(right.msg)] = right_prepend_stamp - // leftAppendStamp = left.ops.add(OpAppend(right.msg)) - //Timestamp leftPrependStamp = left.add(new OpAppend(right.msg)); - left.ops.put(new OpAppend(right.msg), rightPrependStamp); - - // return rightPrependStamp.ops.add(unaryOpCls()) - Timestamp res = rightPrependStamp.add(new OpSHA256()); - return res; - } - - public static Timestamp catSha256(Timestamp left, Timestamp right) { - return Merkle.catThenUnaryOp(left, right); - } - - public static Timestamp catSha256d(Timestamp left, Timestamp right) { - Timestamp sha256Timestamp = Merkle.catSha256(left, right); - // res = sha256Timestamp.ops.add(OpSHA256()); - Timestamp res = sha256Timestamp.add(new OpSHA256()); - return res; - } - - /** - * Merkelize a set of timestamps. - * A merkle tree of all the timestamps is built in-place using binop() to - * timestamp each pair of timestamps. The exact algorithm used is structurally - * identical to a merkle-mountain-range, although leaf sums aren't committed. - * As this function is under the consensus-critical core, it's guaranteed that - * the algorithm will not be changed in the future. - * - * @param timestamps a list of timestamps - * @return the timestamp for the tip of the tree. - */ - public static Timestamp makeMerkleTree(List timestamps) { - List stamps = timestamps; - Timestamp prevStamp = null; - boolean exit = false; - - while (!exit) { - if (stamps.size() > 0) { - prevStamp = stamps.get(0); - } - - List subStamps = stamps.subList(1, stamps.size()); - List nextStamps = new ArrayList<>(); - - for (Timestamp stamp : subStamps) { - if (prevStamp == null) { - prevStamp = stamp; - } else { - nextStamps.add(Merkle.catSha256(prevStamp, stamp)); - prevStamp = null; - } - } - - if (nextStamps.size() == 0) { - exit = true; - } else { - if (prevStamp != null) { - nextStamps.add(prevStamp); - } - - stamps = nextStamps; - } - } - - return prevStamp; - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/OpenTimestamps.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/OpenTimestamps.java deleted file mode 100644 index 809d2f19b..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/OpenTimestamps.java +++ /dev/null @@ -1,485 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -import android.util.Log; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.attestation.BitcoinBlockHeaderAttestation; -import com.vitorpamplona.quartz.nip03Timestamp.ots.attestation.EthereumBlockHeaderAttestation; -import com.vitorpamplona.quartz.nip03Timestamp.ots.attestation.LitecoinBlockHeaderAttestation; -import com.vitorpamplona.quartz.nip03Timestamp.ots.attestation.PendingAttestation; -import com.vitorpamplona.quartz.nip03Timestamp.ots.attestation.TimeAttestation; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.VerificationException; -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpAppend; -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpCrypto; -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpSHA256; -import com.vitorpamplona.quartz.utils.Hex; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * The main class for timestamp operations. - */ -public class OpenTimestamps { - - BitcoinExplorer explorer; - CalendarBuilder calBuilder; - - - public OpenTimestamps(BitcoinExplorer explorer, CalendarBuilder builder) { - this.explorer = explorer; - this.calBuilder = builder; - } - - /** - * Show information on a detached timestamp. - * - * @param detachedTimestampFile The DetachedTimestampFile ots. - * @return the string representation of the timestamp. - */ - public String info(DetachedTimestampFile detachedTimestampFile) { - return info(detachedTimestampFile, false); - } - - /** - * Show information on a detached timestamp with verbose option. - * - * @param detachedTimestampFile The DetachedTimestampFile ots. - * @param verbose Show verbose output. - * @return the string representation of the timestamp. - */ - public String info(DetachedTimestampFile detachedTimestampFile, boolean verbose) { - if (detachedTimestampFile == null) { - return "No ots file"; - } - - String fileHash = Utils.bytesToHex(detachedTimestampFile.timestamp.msg).toLowerCase(Locale.ROOT); - String hashOp = ((OpCrypto) detachedTimestampFile.fileHashOp)._TAG_NAME(); - - String firstLine = "File " + hashOp + " hash: " + fileHash + '\n'; - - return firstLine + "Timestamp:\n" + detachedTimestampFile.timestamp.strTree(0, verbose); - } - - /** - * Show information on a timestamp. - * - * @param timestamp The timestamp buffered. - * @return the string representation of the timestamp. - */ - public String info(Timestamp timestamp) { - if (timestamp == null) { - return "No timestamp"; - } - - String fileHash = Utils.bytesToHex(timestamp.msg).toLowerCase(Locale.ROOT); - String firstLine = "Hash: " + fileHash + '\n'; - - return firstLine + "Timestamp:\n" + timestamp.strTree(0); - } - - /** - * Create timestamp with the aid of a remote calendar. May be specified multiple times. - * - * @param fileTimestamp The Detached Timestamp File. - * @return The plain array buffer of stamped. - * @throws IOException if fileTimestamp is not valid, or the stamp procedure fails. - */ - public Timestamp stamp(DetachedTimestampFile fileTimestamp) throws IOException { - return stamp(fileTimestamp, null, 0); - } - - /** - * Create timestamp with the aid of a remote calendar. May be specified multiple times. - * - * @param fileTimestamp The timestamp to stamp. - * @param calendarsUrl The list of calendar urls. - * @param m The number of calendar to use. - * @return The plain array buffer of stamped. - * @throws IOException if fileTimestamp is not valid, or the stamp procedure fails. - */ - public Timestamp stamp(DetachedTimestampFile fileTimestamp, List calendarsUrl, Integer m) throws IOException { - List fileTimestamps = new ArrayList(); - fileTimestamps.add(fileTimestamp); - - return stamp(fileTimestamps, calendarsUrl, m); - } - - /** - * Create timestamp with the aid of a remote calendar. May be specified multiple times. - * - * @param fileTimestamps The list of timestamp to stamp. - * @param calendarsUrl The list of calendar urls. - * @param m The number of calendar to use. - * @return The plain array buffer of stamped. - * @throws IOException if fileTimestamp is not valid, or the stamp procedure fails. - */ - public Timestamp stamp(List fileTimestamps, List calendarsUrl, Integer m) throws IOException { - // Parse parameters - if (fileTimestamps == null || fileTimestamps.size() == 0) { - throw new IOException(); - } - - if (calendarsUrl == null || calendarsUrl.size() == 0) { - calendarsUrl = new ArrayList(); - calendarsUrl.add("https://alice.btc.calendar.opentimestamps.org"); - calendarsUrl.add("https://bob.btc.calendar.opentimestamps.org"); - calendarsUrl.add("https://finney.calendar.eternitywall.com"); - } - - if (m == null || m <= 0) { - if (calendarsUrl.size() == 0) { - m = 2; - } else if (calendarsUrl.size() == 1) { - m = 1; - } else { - m = calendarsUrl.size(); - } - } - - if (m < 0 || m > calendarsUrl.size()) { - Log.e("OpenTimestamp", "m cannot be greater than available calendar neither less or equal 0"); - throw new IOException(); - } - - // Build markle tree - Timestamp merkleTip = makeMerkleTree(fileTimestamps); - - if (merkleTip == null) { - throw new IOException(); - } - - // Stamping - Timestamp resultTimestamp = create(merkleTip, calendarsUrl, m); - - if (resultTimestamp == null) { - throw new IOException(); - } - - // Result of timestamp serialization - if (fileTimestamps.size() == 1) { - return fileTimestamps.get(0).timestamp; - } else { - return merkleTip; - } - } - - /** - * Create a timestamp - * - * @param timestamp The timestamp. - * @param calendarUrls List of calendar's to use. - * @param m Number of calendars to use. - * @return The created timestamp. - */ - private Timestamp create(Timestamp timestamp, List calendarUrls, Integer m) { - int capacity = calendarUrls.size(); - ExecutorService executor = Executors.newFixedThreadPool(4); - ArrayBlockingQueue> queue = new ArrayBlockingQueue<>(capacity); - - // Submit to all public calendars - for (final String calendarUrl : calendarUrls) { - Log.i("OpenTimestamps", "Submitting to remote calendar " + calendarUrl); - - try { - CalendarAsyncSubmit task = new CalendarAsyncSubmit(calendarUrl, timestamp.msg); - task.setQueue(queue); - executor.submit(task); - } catch (Exception e) { - e.printStackTrace(); - } - } - - int count = 0; - - for (count = 0; count < capacity && count < m; count++) { - try { - Optional optionalStamp = queue.take(); - - if (optionalStamp.isPresent()) { - try { - Timestamp time = optionalStamp.get(); - timestamp.merge(time); - Log.i("Open", ""+ timestamp.attestations.size()); - } catch (Exception e) { - e.printStackTrace(); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - if (count < m) { - Log.e("OpenTimestamp", "Failed to create timestamp: requested " + String.valueOf(m) + " attestation" + ((m > 1) ? "s" : "") + " but received only " + String.valueOf(count)); - } - - //shut down the executor service now - executor.shutdown(); - - return timestamp; - } - - /** - * Make Merkle Tree of detached timestamps. - * - * @param fileTimestamps The list of DetachedTimestampFile. - * @return merkle tip timestamp. - */ - public Timestamp makeMerkleTree(List fileTimestamps) { - List merkleRoots = new ArrayList<>(); - - for (DetachedTimestampFile fileTimestamp : fileTimestamps) { - byte[] bytesRandom16 = new byte[16]; - - try { - bytesRandom16 = Utils.randBytes(16); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - - // nonce_appended_stamp = file_timestamp.timestamp.ops.add(com.vitorpamplona.quartz.ots.op.OpAppend(os.urandom(16))) - Timestamp nonceAppendedStamp = fileTimestamp.timestamp.add(new OpAppend(bytesRandom16)); - // merkle_root = nonce_appended_stamp.ops.add(com.vitorpamplona.quartz.ots.op.OpSHA256()) - Timestamp merkleRoot = nonceAppendedStamp.add(new OpSHA256()); - merkleRoots.add(merkleRoot); - } - - Timestamp merkleTip = Merkle.makeMerkleTree(merkleRoots); - return merkleTip; - } - - /** - * Compare and verify a detached timestamp. - * - * @param ots The DetachedTimestampFile containing the proof to verify. - * @param diggest The hash of the stamped file, in bytes - * @return Hashmap of block heights and timestamps indexed by chain: timestamp in seconds from 1 January 1970. - * @throws Exception if the verification procedure fails. - */ - - public HashMap verify(DetachedTimestampFile ots, byte[] diggest) throws Exception { - if (!Arrays.equals(ots.fileDigest(), diggest)) { - Log.e("OpenTimestamp", "Expected digest " + Hex.encode(ots.fileDigest()).toLowerCase(Locale.ROOT)); - Log.e("OpenTimestamp", "File does not match original!"); - throw new Exception("File does not match original!"); - } - - return verify(ots.timestamp); - } - - /** - * Verify a timestamp. - * - * @param timestamp The timestamp. - * @return HashMap of block heights and timestamps indexed by chain: timestamp in seconds from 1 January 1970. - * @throws Exception if the verification procedure fails. - */ - public HashMap verify(Timestamp timestamp) throws Exception { - HashMap verifyResults = new HashMap<>(); - - for (Map.Entry item : timestamp.allAttestations().entrySet()) { - byte[] msg = item.getKey(); - TimeAttestation attestation = item.getValue(); - VerifyResult verifyResult = null; - VerifyResult.Chains chain = null; - - try { - if (attestation instanceof BitcoinBlockHeaderAttestation) { - chain = VerifyResult.Chains.BITCOIN; - Long time = verify((BitcoinBlockHeaderAttestation) attestation, msg); - int height = ((BitcoinBlockHeaderAttestation) attestation).getHeight(); - verifyResult = new VerifyResult(time, height); - } else if (attestation instanceof LitecoinBlockHeaderAttestation) { - chain = VerifyResult.Chains.LITECOIN; - Long time = verify((LitecoinBlockHeaderAttestation) attestation, msg); - int height = ((LitecoinBlockHeaderAttestation) attestation).getHeight(); - verifyResult = new VerifyResult(time, height); - } - - if (verifyResult != null && verifyResults.containsKey(chain)) { - if (verifyResult.height < verifyResults.get(chain).height) { - verifyResults.put(chain, verifyResult); - } - } - - if (verifyResult != null && !verifyResults.containsKey(chain)) { - verifyResults.put(chain, verifyResult); - } - } catch (VerificationException e) { - throw e; - } catch (Exception e) { - String text = ""; - - if (chain == VerifyResult.Chains.BITCOIN) { - text = BitcoinBlockHeaderAttestation.chain; - } else if (chain == VerifyResult.Chains.LITECOIN) { - text = LitecoinBlockHeaderAttestation.chain; - } else if (chain == VerifyResult.Chains.ETHEREUM) { - text = EthereumBlockHeaderAttestation.chain; - } else { - throw e; - } - - Log.e("OpenTimestamp", Utils.toUpperFirstLetter(text) + " verification failed: " + e.getMessage()); - throw e; - } - } - return verifyResults; - } - - /** - * Verify an Bitcoin Block Header Attestation. - * if the node is not reachable or it fails, uses Lite-client verification. - * - * @param attestation The BitcoinBlockHeaderAttestation attestation. - * @param msg The digest to verify. - * @return The unix timestamp in seconds from 1 January 1970. - * @throws VerificationException if it doesn't check the merkle root of the block. - * @throws Exception if the verification procedure fails. - */ - public Long verify(BitcoinBlockHeaderAttestation attestation, byte[] msg) throws VerificationException, Exception { - Integer height = attestation.getHeight(); - BlockHeader blockInfo; - - try { - String blockHash = explorer.blockHash(height); - blockInfo = explorer.block(blockHash); - Log.i("OpenTimestamps", "Lite-client verification, assuming block " + blockHash + " is valid"); - } catch (Exception e2) { - e2.printStackTrace(); - throw e2; - } - - return attestation.verifyAgainstBlockheader(Utils.arrayReverse(msg), blockInfo); - } - - /** - * Verify an Litecoin Block Header Attestation. Litecoin verification uses only lite-client verification. - * - * @param attestation The LitecoinBlockHeaderAttestation attestation. - * @param msg The digest to verify. - * @return The unix timestamp in seconds from 1 January 1970. - * @throws VerificationException if it doesn't check the merkle root of the block. - * @throws Exception if the verification procedure fails. - */ - public Long verify(LitecoinBlockHeaderAttestation attestation, byte[] msg) throws VerificationException, Exception { - Integer height = attestation.getHeight(); - BlockHeader blockInfo; - - try { - String blockHash = explorer.blockHash(height); - Log.i("OpenTimestamps", "Lite-client verification, assuming block " + blockHash + " is valid"); - blockInfo = explorer.block(blockHash); - } catch (Exception e2) { - e2.printStackTrace(); - throw e2; - } - - return attestation.verifyAgainstBlockheader(Utils.arrayReverse(msg), blockInfo); - } - - /** - * Upgrade a timestamp. - * - * @param detachedTimestamp The DetachedTimestampFile containing the proof to verify. - * @return a boolean representing if the timestamp has changed. - * @throws Exception if the upgrading procedure fails. - */ - public boolean upgrade(DetachedTimestampFile detachedTimestamp) throws Exception { - // Upgrade timestamp - boolean changed = upgrade(detachedTimestamp.timestamp); - return changed; - } - - /** - * Attempt to upgrade an incomplete timestamp to make it verifiable. - * Note that this means if the timestamp that is already complete, False will be returned as nothing has changed. - * - * @param timestamp The timestamp to upgrade. - * @return a boolean representing if the timestamp has changed. - * @throws Exception if the upgrading procedure fails. - */ - public boolean upgrade(Timestamp timestamp) throws Exception { - // Check remote calendars for upgrades. - // This time we only check PendingAttestations - we can't be as agressive. - - boolean upgraded = false; - Set existingAttestations = timestamp.getAttestations(); - - for (Timestamp subStamp : timestamp.directlyVerified()) { - for (TimeAttestation attestation : subStamp.attestations) { - if (attestation instanceof PendingAttestation && !subStamp.isTimestampComplete()) { - String calendarUrl = new String(((PendingAttestation) attestation).getUri(), StandardCharsets.UTF_8); - // var calendarUrl = calendarUrls[0]; - byte[] commitment = subStamp.msg; - - try { - Calendar calendar = new Calendar(calendarUrl); - Timestamp upgradedStamp = upgrade(subStamp, calendar, commitment, existingAttestations); - - try { - subStamp.merge(upgradedStamp); - } catch (Exception e) { - e.printStackTrace(); - } - - upgraded = true; - } catch (Exception e) { - Log.i("OpenTimestamps", e.getMessage()); - } - } - } - } - - return upgraded; - } - - private Timestamp upgrade(Timestamp subStamp, Calendar calendar, byte[] commitment, Set existingAttestations) throws Exception { - Timestamp upgradedStamp; - - try { - upgradedStamp = calendar.getTimestamp(commitment); - - if (upgradedStamp == null) { - throw new Exception("Invalid stamp"); - } - } catch (Exception e) { - Log.i("OpenTimestamps", "Calendar " + calendar.getUrl() + ": " + e.getMessage()); - throw e; - } - - Set attsFromRemote = upgradedStamp.getAttestations(); - - if (attsFromRemote.size() > 0) { - Log.i("OpenTimestamps", "Got 1 attestation(s) from " + calendar.getUrl()); - } - - // Set difference from remote attestations & existing attestations - Set newAttestations = attsFromRemote; - newAttestations.removeAll(existingAttestations); - - // changed & found_new_attestations - // foundNewAttestations = true; - // Log.i("OpenTimestamps", attsFromRemote.size + ' attestation(s) from ' + calendar.url); - - // Set union of existingAttestations & newAttestations - existingAttestations.addAll(newAttestations); - - return upgradedStamp; - // subStamp.merge(upgradedStamp); - // args.cache.merge(upgraded_stamp) - // sub_stamp.merge(upgraded_stamp) - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamDeserializationContext.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamDeserializationContext.java deleted file mode 100644 index 96e1b0679..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamDeserializationContext.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException; - -import java.util.Arrays; - -public class StreamDeserializationContext { - - byte[] buffer; - int counter = 0; - - public StreamDeserializationContext(byte[] stream) { - this.buffer = stream; - this.counter = 0; - } - - public byte[] getOutput() { - return this.buffer; - } - - public int getCounter() { - return this.counter; - } - - public byte[] read(int l) { - if (this.counter == this.buffer.length) { - return null; - } - - if (l+this.counter > this.buffer.length) { - l = this.buffer.length-this.counter; - } - - // const uint8Array = new Uint8Array(this.buffer,this.counter,l); - byte[] uint8Array = Arrays.copyOfRange(this.buffer, this.counter, this.counter + l); - this.counter += l; - - return uint8Array; - } - - public boolean readBool() { - byte b = this.read(1)[0]; - - if (b == 0xff) { - return true; - } else if (b == 0x00) { - return false; - } - - return false; - } - - public int readVaruint() { - int value = 0; - byte shift = 0; - byte b; - - do { - b = this.read(1)[0]; - value |= (b & 0b01111111) << shift; - shift += 7; - } while ((b & 0b10000000) != 0b00000000); - - return value; - } - - public byte[] readBytes(int expectedLength) throws DeserializationException { - - - if (expectedLength == 0) { - return this.readVarbytes(1024, 0); - } - - return this.read(expectedLength); - } - - public byte[] readVarbytes(int maxLen) throws DeserializationException { - return readVarbytes(maxLen, 0); - } - - public byte[] readVarbytes(int maxLen, int minLen) throws DeserializationException { - int l = this.readVaruint(); - - if (l > maxLen) { - throw new DeserializationException("varbytes max length exceeded;"); - } else if (l < minLen) { - throw new DeserializationException("varbytes min length not met;"); - } - - return this.read(l); - } - - public boolean assertMagic(byte[] expectedMagic) { - byte[] actualMagic = this.read(expectedMagic.length); - - return Arrays.equals(expectedMagic, actualMagic); - } - - public boolean assertEof() { - byte[] excess = this.read(1); - return excess != null; - } - - public String toString() { - return Arrays.toString(this.buffer); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamSerializationContext.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamSerializationContext.java deleted file mode 100644 index a95b4229a..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/StreamSerializationContext.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class StreamSerializationContext { - - List buffer = new ArrayList<>(); - - public StreamSerializationContext() { - this.buffer = new ArrayList<>(); - } - - public byte[] getOutput() { - byte[] bytes = new byte[this.buffer.size()]; - - for (int i = 0; i < this.buffer.size(); i++) { - bytes[i] = this.buffer.get(i); - } - - return bytes; - } - - public int getLength() { - return this.buffer.size(); - } - - public void writeBool(boolean value) { - if (value) { - this.writeByte((byte) 0xff); - } else { - this.writeByte((byte) 0x00); - } - } - - public void writeVaruint(int value) { - if ((value) == 0b00000000) { - this.writeByte((byte) 0x00); - } else { - while (value != 0) { - byte b = (byte) ((value & 0xff) & 0b01111111); - - if ((value) > 0b01111111) { - b |= 0b10000000; - } - - this.writeByte(b); - - if ((value) <= 0b01111111) { - break; - } - - value = value >> 7; - } - } - } - - public void writeByte(byte value) { - this.buffer.add(Byte.valueOf(value)); - } - - public void writeByte(Byte value) { - this.buffer.add(value); - } - - public void writeBytes(byte[] value) { - for (byte b : value) { - this.writeByte(b); - } - } - - public void writeVarbytes(byte[] value) { - this.writeVaruint(value.length); - this.writeBytes(value); - } - - public String toString() { - return Arrays.toString(this.getOutput()); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Timestamp.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Timestamp.java deleted file mode 100644 index eff52a3c2..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Timestamp.java +++ /dev/null @@ -1,627 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.attestation.BitcoinBlockHeaderAttestation; -import com.vitorpamplona.quartz.nip03Timestamp.ots.attestation.TimeAttestation; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException; -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.Op; -import com.vitorpamplona.quartz.nip03Timestamp.ots.op.OpBinary; -import com.vitorpamplona.quartz.utils.Hex; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeMap; - -/** - * Proof that one or more attestations commit to a message. - * The proof is in the form of a tree, with each node being a message, and the - * edges being operations acting on those messages. The leafs of the tree are - * attestations that attest to the time that messages in the tree existed prior. - */ -public class Timestamp { - - public byte[] msg; - public List attestations; - public HashMap ops; - - /** - * Create a com.vitorpamplona.quartz.ots.Timestamp object. - * - * @param msg - Desc - */ - public Timestamp(byte[] msg) { - this.msg = msg; - this.attestations = new ArrayList<>(); - this.ops = new HashMap<>(); - } - - /** - * Deserialize a Timestamp. - * - * @param ots - The serialized byte array. - * @param initialMsg - The initial message. - * @return The deserialized Timestamp. - */ - public static Timestamp deserialize(byte[] ots, byte[] initialMsg) throws DeserializationException { - StreamDeserializationContext ctx = new StreamDeserializationContext(ots); - - return Timestamp.deserialize(ctx, initialMsg); - } - - /** - * Deserialize a Timestamp. - * Because the serialization format doesn't include the message that the - * timestamp operates on, you have to provide it so that the correct - * operation results can be calculated. - * The message you provide is assumed to be correct; if it causes a op to - * raise MsgValueError when the results are being calculated (done - * immediately, not lazily) DeserializationError is raised instead. - * - * @param ctx - The stream deserialization context. - * @param initialMsg - The initial message. - * @return The deserialized Timestamp. - */ - public static Timestamp deserialize(StreamDeserializationContext ctx, byte[] initialMsg) - throws DeserializationException { - Timestamp self = new Timestamp(initialMsg); - byte tag = ctx.readBytes(1)[0]; - - while ((tag & 0xff) == 0xff) { - byte current = ctx.readBytes(1)[0]; - doTagOrAttestation(self, ctx, current, initialMsg); - tag = ctx.readBytes(1)[0]; - } - - doTagOrAttestation(self, ctx, tag, initialMsg); - - return self; - } - - private static void doTagOrAttestation(Timestamp self, StreamDeserializationContext ctx, byte tag, byte[] initialMsg) - throws DeserializationException { - if ((tag & 0xff) == 0x00) { - TimeAttestation attestation = TimeAttestation.deserialize(ctx); - self.attestations.add(attestation); - } else { - Op op = Op.deserializeFromTag(ctx, tag); - byte[] result = op.call(initialMsg); - - Timestamp stamp = Timestamp.deserialize(ctx, result); - self.ops.put(op, stamp); - } - } - - /** - * Create a Serialize object. - * - * @return The byte array of the serialized timestamp - */ - public byte[] serialize() { - StreamSerializationContext ctx = new StreamSerializationContext(); - serialize(ctx); - - return ctx.getOutput(); - } - - /** - * Create a Serialize object. - * - * @param ctx - The stream serialization context. - */ - public void serialize(StreamSerializationContext ctx) { - List sortedAttestations = this.attestations; // TODO: Hm, this is just a reference copy... - Collections.sort(sortedAttestations); - - if (sortedAttestations.size() > 1) { - for (int i = 0; i < sortedAttestations.size() - 1; i++) { - ctx.writeBytes(new byte[]{(byte) 0xff, (byte) 0x00}); - sortedAttestations.get(i).serialize(ctx); - } - } - - if (this.ops.isEmpty()) { - ctx.writeByte((byte) 0x00); - - if (!sortedAttestations.isEmpty()) { - sortedAttestations.get(sortedAttestations.size() - 1).serialize(ctx); - } - } else if (!this.ops.isEmpty()) { - if (!sortedAttestations.isEmpty()) { - ctx.writeBytes(new byte[]{(byte) 0xff, (byte) 0x00}); - sortedAttestations.get(sortedAttestations.size() - 1).serialize(ctx); - } - - int counter = 0; - List> list = sortToList(this.ops.entrySet()); - - for (Map.Entry entry : list) { - Timestamp stamp = entry.getValue(); - Op op = entry.getKey(); - - if (counter < this.ops.size() - 1) { - ctx.writeBytes(new byte[]{(byte) 0xff}); - counter++; - } - - op.serialize(ctx); - stamp.serialize(ctx); - } - } - } - - /** - * Add all operations and attestations from another timestamp to this one. - * - * @param other - Initial other com.vitorpamplona.quartz.ots.Timestamp to merge. - * @throws Exception different timestamps messages - */ - public void merge(Timestamp other) throws Exception { - if (!Arrays.equals(this.msg, other.msg)) { - //Log.e("OpenTimestamp", "Can\'t merge timestamps for different messages together"); - throw new Exception("Can\'t merge timestamps for different messages together"); - } - - for (final TimeAttestation attestation : other.attestations) { - this.attestations.add(attestation); - } - - for (Map.Entry entry : other.ops.entrySet()) { - Timestamp otherOpStamp = entry.getValue(); - Op otherOp = entry.getKey(); - - Timestamp ourOpStamp = this.ops.get(otherOp); - - if (ourOpStamp == null) { - ourOpStamp = new Timestamp(otherOp.call(this.msg)); - this.ops.put(otherOp, ourOpStamp); - } - - ourOpStamp.merge(otherOpStamp); - } - } - - /** - * Shrink Timestamp. - * Remove useless pending attestions if exist a full bitcoin attestation. - * - * @return TimeAttestation - the minimal attestation. - * @throws Exception no attestion founds. - */ - public TimeAttestation shrink() throws Exception { - // Get all attestations - HashMap allAttestations = this.allAttestations(); - - if (allAttestations.size() == 0) { - throw new Exception(); - } else if (allAttestations.size() == 1) { - return allAttestations.values().iterator().next(); - } else if (this.ops.size() == 0) { - throw new Exception(); // TODO: Need a descriptive exception string here - } - - // Fore >1 attestations : - // Search first BitcoinBlockHeaderAttestation - TimeAttestation minAttestation = null; - - for (Map.Entry entry : this.ops.entrySet()) { - Timestamp timestamp = entry.getValue(); - //Op op = entry.getKey(); - - for (TimeAttestation attestation : timestamp.getAttestations()) { - if (attestation instanceof BitcoinBlockHeaderAttestation) { - if (minAttestation == null) { - minAttestation = attestation; - } else { - if (minAttestation instanceof BitcoinBlockHeaderAttestation - && attestation instanceof BitcoinBlockHeaderAttestation - && ((BitcoinBlockHeaderAttestation) minAttestation).getHeight() - > ((BitcoinBlockHeaderAttestation) attestation).getHeight()) { - minAttestation = attestation; - } - } - } - } - } - - // Only pending attestations : return the first - if (minAttestation == null) { - return allAttestations.values().iterator().next(); - } - - // Remove attestation if not min attestation - boolean shrinked = false; - - for (Iterator> it = this.ops.entrySet().iterator(); it.hasNext(); ) { - Map.Entry entry = it.next(); - Timestamp timestamp = entry.getValue(); - Op op = entry.getKey(); - Set attestations = timestamp.getAttestations(); - - if (attestations.size() > 0 && attestations.contains(minAttestation) && shrinked == false) { - timestamp.shrink(); - shrinked = true; - } else { - it.remove(); - } - } - - return minAttestation; - } - - /** - * Return the digest of the timestamp. - * - * @return The byte[] digest string. - */ - public byte[] getDigest() { - return this.msg; - } - - /** - * Return as memory hierarchical object. - * - * @param indent - Initial hierarchical indention. - * @return The output string. - */ - public String toString(int indent) { - StringBuilder builder = new StringBuilder(); - builder.append(Timestamp.indention(indent) + "msg: " + Hex.encode(this.msg) + "\n"); - builder.append(Timestamp.indention(indent) + this.attestations.size() + " attestations: \n"); - int i = 0; - - for (final TimeAttestation attestation : this.attestations) { - builder.append(Timestamp.indention(indent) + "[" + i + "] " + attestation.toString() + "\n"); - i++; - } - - i = 0; - builder.append(Timestamp.indention(indent) + this.ops.size() + " ops: \n"); - - for (Map.Entry entry : this.ops.entrySet()) { - Timestamp stamp = entry.getValue(); - Op op = entry.getKey(); - - builder.append(Timestamp.indention(indent) + "[" + i + "] op: " + op.toString() + "\n"); - builder.append(Timestamp.indention(indent) + "[" + i + "] timestamp: \n"); - builder.append(stamp.toString(indent + 1)); - i++; - } - - builder.append('\n'); - - return builder.toString(); - } - - /** - * Indention function for printing tree. - * - * @param pos - Initial hierarchical indention. - * @return The output space string. - */ - public static String indention(int pos) { - StringBuilder builder = new StringBuilder(); - - for (int i = 0; i < pos; i++) { - builder.append(" "); - } - - return builder.toString(); - } - - public String strTree(int indent) { - return strTree(indent, false); - } - - private String strResult(boolean verbosity, byte[] parameter, byte[] result) { - final String ANSI_HEADER = "\u001B[95m"; - final String ANSI_OKBLUE = "\u001B[94m"; - final String ANSI_OKGREEN = "\u001B[92m"; - final String ANSI_WARNING = "\u001B[93m"; - final String ANSI_FAIL = "\u001B[91m"; - final String ANSI_ENDC = "\u001B[0m"; - final String ANSI_BOLD = "\u001B[1m"; - final String ANSI_UNDERLINE = "\u001B[4m"; - - String rr = ""; - - if (verbosity == true && result != null) { - rr += " == "; - String resultHex = Utils.bytesToHex(result); - - if (parameter == null) { - rr += resultHex; - } else { - String parameterHex = Utils.bytesToHex(parameter); - - try { - int index = resultHex.indexOf(parameterHex); - String parameterHexHighlight = ANSI_BOLD + parameterHex + ANSI_ENDC; - - if (index == 0) { - rr += parameterHexHighlight + resultHex.substring(index + parameterHex.length(), resultHex.length()); - } else { - rr += resultHex.substring(0, index) + parameterHexHighlight; - } - } catch (Exception err) { - rr += resultHex; - } - } - } - - return rr; - } - - /** - * Return as tree hierarchical object. - * - * @param indent - Initial hierarchical indention. - * @param verbosity - Verbose option. - * @return The output string. - */ - public String strTree(int indent, boolean verbosity) { - StringBuilder builder = new StringBuilder(); - - if (!this.attestations.isEmpty()) { - for (final TimeAttestation attestation : this.attestations) { - builder.append(Timestamp.indention(indent)); - builder.append("verify " + attestation.toString() + strResult(verbosity, this.msg, null) + "\n"); - - if (attestation instanceof BitcoinBlockHeaderAttestation) { - String tx = Utils.bytesToHex(Utils.arrayReverse(this.msg)); - builder.append(Timestamp.indention(indent) + "# Bitcoin block merkle root " + tx.toLowerCase(Locale.ROOT) + "\n"); - } - } - } - - if (this.ops.size() > 1) { - TreeMap ordered = new TreeMap<>(this.ops); - - for (Map.Entry entry : ordered.entrySet()) { - Timestamp timestamp = entry.getValue(); - Op op = entry.getKey(); - - byte[] curRes = op.call(this.msg); - byte[] curPar = null; - - if (op instanceof OpBinary) { - curPar = ((OpBinary) op).arg; - } - - builder.append(Timestamp.indention(indent) + " -> " + op.toString().toLowerCase(Locale.ROOT) + strResult(verbosity, curPar, curRes).toLowerCase(Locale.ROOT) + "\n"); - builder.append(timestamp.strTree(indent + 1, verbosity)); - } - } else if (this.ops.size() > 0) { - // output += com.eternitywall.ots.Timestamp.indention(indent); - for (Map.Entry entry : this.ops.entrySet()) { - Timestamp timestamp = entry.getValue(); - Op op = entry.getKey(); - - byte[] curRes = op.call(this.msg); - byte[] curPar = null; - - if (op instanceof OpBinary) { - curPar = ((OpBinary) op).arg; - } - - builder.append(Timestamp.indention(indent) + op.toString().toLowerCase(Locale.ROOT) + strResult(verbosity, curPar, curRes).toLowerCase(Locale.ROOT) + "\n"); - builder.append(timestamp.strTree(indent, verbosity)); - } - } - - return builder.toString(); - } - - /** - * Returns a list of all sub timestamps with attestations. - * - * @return List of all sub timestamps with attestations. - */ - public List directlyVerified() { - if (!this.attestations.isEmpty()) { - List list = new ArrayList<>(); - list.add(this); - return list; - } - - List list = new ArrayList<>(); - - for (Map.Entry entry : this.ops.entrySet()) { - Timestamp ts = entry.getValue(); - //Op op = entry.getKey(); - - List result = ts.directlyVerified(); - list.addAll(result); - } - - return list; - } - - /** - * Returns a set of all Attestations. - * - * @return Set of all timestamp attestations. - */ - public Set getAttestations() { - Set set = new HashSet(); - - for (Map.Entry item : this.allAttestations().entrySet()) { - //byte[] msg = item.getKey(); - TimeAttestation attestation = item.getValue(); - set.add(attestation); - } - - return set; - } - - /** - * Determine if timestamp is complete and can be verified. - * - * @return True if the timestamp is complete, False otherwise. - */ - public Boolean isTimestampComplete() { - for (Map.Entry item : this.allAttestations().entrySet()) { - //byte[] msg = item.getKey(); - TimeAttestation attestation = item.getValue(); - - if (attestation instanceof BitcoinBlockHeaderAttestation) { - return true; - } - } - - return false; - } - - /** - * Iterate over all attestations recursively - * - * @return Returns iterable of (msg, attestation) - */ - public HashMap allAttestations() { - HashMap map = new HashMap<>(); - - for (TimeAttestation attestation : this.attestations) { - map.put(this.msg, attestation); - } - - for (Map.Entry entry : this.ops.entrySet()) { - Timestamp ts = entry.getValue(); - //Op op = entry.getKey(); - - HashMap subMap = ts.allAttestations(); - - for (Map.Entry item : subMap.entrySet()) { - byte[] msg = item.getKey(); - TimeAttestation attestation = item.getValue(); - map.put(msg, attestation); - } - } - - return map; - } - - /** - * Iterate over all tips recursively - * - * @return Returns iterable of (msg, attestation) - */ - public Set allTips() { - Set set = new HashSet<>(); - - if (this.ops.size() == 0) { - set.add(this.msg); - } - - for (Map.Entry entry : this.ops.entrySet()) { - Timestamp ts = entry.getValue(); - //Op op = entry.getKey(); - - Set subSet = ts.allTips(); - - for (byte[] msg : subSet) { - set.add(msg); - } - } - - return set; - } - - /** - * Compare timestamps. - * - * @param timestamp the timestamp to compare with - * @return Returns true if timestamps are equals - */ - public boolean equals(Timestamp timestamp) { - if (Arrays.equals(this.getDigest(), timestamp.getDigest()) == false) { - return false; - } - - // Check attestations - if (this.attestations.size() != timestamp.attestations.size()) { - return false; - } - - for (int i = 0; i < this.attestations.size(); i++) { - TimeAttestation ta1 = this.attestations.get(i); - TimeAttestation ta2 = timestamp.attestations.get(i); - - if (!(ta1.equals(ta2))) { - return false; - } - } - - // Check operations - if (this.ops.size() != timestamp.ops.size()) { - return false; - } - - // Order list of operations - List> list1 = sortToList(this.ops.entrySet()); - List> list2 = sortToList(timestamp.ops.entrySet()); - - for (int i = 0; i < list1.size(); i++) { - Op op1 = list1.get(i).getKey(); - Op op2 = list2.get(i).getKey(); - - if (!op1.equals(op2)) { - return false; - } - - Timestamp t1 = list1.get(i).getValue(); - Timestamp t2 = list2.get(i).getValue(); - - if (!t1.equals(t2)) { - return false; - } - } - - return true; - } - - /** - * Add Op to current timestamp and return the sub stamp - * - * @param op - The operation to insert - * @return Returns the sub timestamp - */ - public Timestamp add(Op op) { - // nonce_appended_stamp = timestamp.ops.add(com.vitorpamplona.quartz.ots.op.OpAppend(os.urandom(16))) - //Op opAppend = new OpAppend(bytes); - - if (this.ops.containsKey(op)) { - return this.ops.get(op); - } - - Timestamp stamp = new Timestamp(op.call(this.msg)); - this.ops.put(op, stamp); - - return stamp; - } - - /** - * Retrieve a sorted list of all map entries. - * - * @param setEntries - The entries set of ops hashmap - * @return Returns the sorted list of map entries - */ - public List> sortToList(Set> setEntries) { - List> entries = new ArrayList<>(setEntries); - Collections.sort(entries, new Comparator>() { - @Override - public int compare(Entry a, Entry b) { - return a.getKey().compareTo(b.getKey()); - } - }); - - return entries; - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Utils.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Utils.java deleted file mode 100644 index fdc2895dd..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/Utils.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.util.Locale; -import java.util.logging.ConsoleHandler; -import java.util.logging.LogRecord; -import java.util.logging.Logger; -import java.util.logging.SimpleFormatter; - -/** - * Utility functions for (mostly) manipulating byte arrays. - */ -public class Utils { - /** - * Fills a byte array with the given byte value. - * - * @param array the array to fill - * @param value the value to fill the array with - */ - public static void arrayFill(byte[] array, byte value) { - for (int i = 0; i < array.length; i++) { - array[i] = value; - } - } - - /** - * Returns the first value that is not null. If all objects are null, then it returns null. - * - * @param items the array of Ts - * @param This describes my type parameter - * @return the first value that is not null. If all objects are null, then it returns null. - * @deprecated Not used by Java OpenTimestamps itself, and doesn't offer much useful functionality. - */ - @Deprecated - public static T coalesce(T... items) { - for (T i : items) { - if (i != null) { - return i; - } - } - - return null; - } - - /** - * Returns a copy of the byte array argument, or null if the byte array argument is null. - * - * @param data the array of bytes to copy - * @return the copied byte array - */ - public static byte[] arraysCopy(byte[] data) { - if (data == null) { - return null; - } - - byte[] copy = new byte[data.length]; - System.arraycopy(data, 0, copy, 0, data.length); - - return copy; - } - - /** - * Returns a byte array which is the result of concatenating the two passed in byte arrays. - * None of the passed in arrays may be null. - * - * @param array1 the first array of bytes - * @param array2 the second array of bytes - * @return a copy of array1 and array2 concatenated together - */ - public static byte[] arraysConcat(byte[] array1, byte[] array2) { - byte[] array1and2 = new byte[array1.length + array2.length]; - System.arraycopy(array1, 0, array1and2, 0, array1.length); - System.arraycopy(array2, 0, array1and2, array1.length, array2.length); - - return array1and2; - } - - /** - * Returns a given length array of random bytes. - * - * @param length the requested length of the byte array - * @return a given length array of random bytes - * @throws NoSuchAlgorithmException for Java 8 implementations - */ - public static byte[] randBytes(int length) throws NoSuchAlgorithmException { - //Java 6 & 7: - SecureRandom random = new SecureRandom(); - byte[] bytes = new byte[length]; - random.nextBytes(bytes); - - // Java 8 (even more secure): - // SecureRandom.getInstanceStrong().nextBytes(bytes); - - return bytes; - } - - /** - * Returns a reversed copy of the passed in byte array. - * - * @param array the byte array to reverse - * @return a copy of the byte array, reversed - */ - public static byte[] arrayReverse(byte[] array) { - byte[] reversedArray = new byte[array.length]; - - for (int i = array.length - 1, j = 0; i >= 0; i--, j++) { - reversedArray[j] = array[i]; - } - - return reversedArray; - } - - /** - * Compares two byte arrays. - * - * @param left the left byte array to compare with - * @param right the right byte array to compare with - * @return 0 if the arrays are identical, negative if left < right, positive if left > right - */ - public static int compare(byte[] left, byte[] right) { - for (int i = 0, j = 0; i < left.length && j < right.length; i++, j++) { - int a = (left[i] & 0xff); - int b = (right[j] & 0xff); - - if (a != b) { - return a - b; - } - } - - return left.length - right.length; - } - - /** - * Returns a HEX representation of the passed in byte array. - * - * @param bytes the byte array to convert into a string of HEX - * @return a string representation of the byte array - */ - public static String bytesToHex(byte[] bytes) { - StringBuilder sb = new StringBuilder(); - - for (byte b : bytes) { - sb.append(String.format("%02X", b)); - } - - return sb.toString(); - } - - /** - * Converts a HEX representation to its byte array representation. The passed in string must not be null. - * - * @param s a string in HEX format to be converted to a corresponding byte array - * @return the byte array representation of the string in HEX format - * @throws IllegalArgumentException if the passed in HEX string can't be converted to a byte array - */ - public static byte[] hexToBytes(String s) throws IllegalArgumentException { - int len = s.length(); - - if (len % 2 == 1) { - throw new IllegalArgumentException(); - } - - byte[] data = new byte[len / 2]; - - for (int i = 0; i < len; i += 2) { - if ((Character.digit(s.charAt(i), 16) == -1) || (Character.digit(s.charAt(i + 1), 16) == -1)) { - throw new IllegalArgumentException(); - } - - data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) - + Character.digit(s.charAt(i + 1), 16)); - } - - return data; - } - - /** - * Returns a string with the first letter uppercase. - * - * @param string the string to get its first character converted to uppercase - * @return the string, with its first character converted to uppercase - */ - public static String toUpperFirstLetter(String string) { - return string.substring(0, 1).toUpperCase(Locale.getDefault()) + string.substring(1).toLowerCase(Locale.getDefault()); - } - - // TODO: This is not the way to do logging. Fix later, possibly with slf4j annotation. Need to read up on the subject. - public static Logger getLogger(String name) { - Logger log = Logger.getLogger(name); - ConsoleHandler handler = new ConsoleHandler(); - - handler.setFormatter(new SimpleFormatter() { - @Override - public synchronized String format(LogRecord lr) { - return lr.getMessage() + "\r\n"; - } - }); - - log.setUseParentHandlers(false); - log.addHandler(handler); - - return log; - } -} \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/VerifyResult.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/VerifyResult.java deleted file mode 100644 index 51b48ab0b..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/VerifyResult.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots; - -import android.annotation.SuppressLint; - -import java.text.DateFormatSymbols; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; - -/** - * Class that lets us compare, sort, store and print timestamps. - */ -public class VerifyResult implements Comparable { - public static enum Chains { - BITCOIN, LITECOIN, ETHEREUM - } - - public Long timestamp; - public int height; - - public VerifyResult(Long timestamp, int height) { - this.timestamp = timestamp; - this.height = height; - } - - /** - * Returns, if existing, a string representation describing the existence of a block attest - */ - public String toString() { - if (height == 0 || timestamp == null) { - return ""; - } - - String pattern = "yyyy-MM-dd z"; - Locale locale = new Locale("en", "UK"); - DateFormatSymbols dateFormatSymbols = new DateFormatSymbols(locale); - @SuppressLint("SimpleDateFormat") - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern, dateFormatSymbols); - String string = simpleDateFormat.format(new Date(timestamp * 1000)); - - return "block " + String.valueOf(height) + " attests data existed as of " + string; - } - - @Override - public int compareTo(VerifyResult vr) { - return this.height - vr.height; - } - - @Override - public boolean equals(Object obj) { - VerifyResult vr = (VerifyResult) obj; - return this.timestamp == vr.timestamp && this.height == vr.height; - } - - @Override - public int hashCode() { - return ((int) (long) (this.timestamp)) ^ this.height; - } -} \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/BitcoinBlockHeaderAttestation.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/BitcoinBlockHeaderAttestation.java deleted file mode 100644 index abb74bd9f..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/BitcoinBlockHeaderAttestation.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.attestation; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.BlockHeader; -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamSerializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.VerificationException; - -import java.util.Arrays; - -/** - * Bitcoin Block Header Attestation. - * The commitment digest will be the merkleroot of the blockheader. - * The block height is recorded so that looking up the correct block header in - * an external block header database doesn't require every header to be stored - * locally (33MB and counting). (remember that a memory-constrained local - * client can save an MMR that commits to all blocks, and use an external service to fill - * in pruned details). - * Otherwise no additional redundant data about the block header is recorded. - * This is very intentional: since the attestation contains (nearly) the - * absolute bare minimum amount of data, we encourage implementations to do - * the correct thing and get the block header from a by-height index, check - * that the merkleroots match, and then calculate the time from the header - * information. Providing more data would encourage implementations to cheat. - * Remember that the only thing that would invalidate the block height is a - * reorg, but in the event of a reorg the merkleroot will be invalid anyway, - * so there's no point to recording data in the attestation like the header - * itself. At best that would just give us extra confirmation that a reorg - * made the attestation invalid; reorgs deep enough to invalidate timestamps are - * exceptionally rare events anyway, so better to just tell the user the timestamp - * can't be verified rather than add almost-never tested code to handle that case - * more gracefully. - * - * @see TimeAttestation - */ -public class BitcoinBlockHeaderAttestation extends TimeAttestation { - - public static byte[] _TAG = {(byte) 0x05, (byte) 0x88, (byte) 0x96, (byte) 0x0d, (byte) 0x73, (byte) 0xd7, (byte) 0x19, (byte) 0x01}; - public static String chain = "bitcoin"; - - @Override - public byte[] _TAG() { - return BitcoinBlockHeaderAttestation._TAG; - } - - private int height = 0; - - public int getHeight() { - return height; - } - - public BitcoinBlockHeaderAttestation(int height_) { - super(); - this.height = height_; - } - - public static BitcoinBlockHeaderAttestation deserialize(StreamDeserializationContext ctxPayload) { - int height = ctxPayload.readVaruint(); - - return new BitcoinBlockHeaderAttestation(height); - } - - @Override - public void serializePayload(StreamSerializationContext ctx) { - ctx.writeVaruint(this.height); - } - - public String toString() { - return "BitcoinBlockHeaderAttestation(" + this.height + ")"; - } - - @Override - public int compareTo(TimeAttestation o) { - BitcoinBlockHeaderAttestation ob = (BitcoinBlockHeaderAttestation) o; - - return this.height - ob.height; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof BitcoinBlockHeaderAttestation)) { - return false; - } - - if (!Arrays.equals(this._TAG(), ((BitcoinBlockHeaderAttestation) obj)._TAG())) { - return false; - } - - if (this.height != ((BitcoinBlockHeaderAttestation) obj).height) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - return Arrays.hashCode(this._TAG()) ^ this.height; - } - - /** - * Verify attestation against a Bitcoin block header. - * @param digest the digest - * @param block the Bitcoin block header - * @return the block time on success; raises VerificationError on failure. - * @throws VerificationException verification exception - */ - public Long verifyAgainstBlockheader(byte[] digest, BlockHeader block) throws VerificationException { - if (digest.length != 32) { - throw new VerificationException("Expected digest with length 32 bytes; got " + digest.length + " bytes"); - } else if (!Arrays.equals(digest, Utils.hexToBytes(block.getMerkleroot()))) { - throw new VerificationException("Digest does not match merkleroot"); - } - - return block.getTime(); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/EthereumBlockHeaderAttestation.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/EthereumBlockHeaderAttestation.java deleted file mode 100644 index e0d514275..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/EthereumBlockHeaderAttestation.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.attestation; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamSerializationContext; - -import java.util.Arrays; - -/** - * Ethereum Block Header Attestation. - * - * @see TimeAttestation - */ -public class EthereumBlockHeaderAttestation extends TimeAttestation { - - public static byte[] _TAG = {(byte) 0x30, (byte) 0xfe, (byte) 0x80, (byte) 0x87, (byte) 0xb5, (byte) 0xc7, (byte) 0xea, (byte) 0xd7}; - public static String chain = "ethereum"; - - @Override - public byte[] _TAG() { - return EthereumBlockHeaderAttestation._TAG; - } - - private int height = 0; - - public int getHeight() { - return height; - } - - EthereumBlockHeaderAttestation(int height_) { - super(); - this.height = height_; - } - - public static EthereumBlockHeaderAttestation deserialize(StreamDeserializationContext ctxPayload) { - int height = ctxPayload.readVaruint(); - - return new EthereumBlockHeaderAttestation(height); - } - - @Override - public void serializePayload(StreamSerializationContext ctx) { - ctx.writeVaruint(this.height); - } - - public String toString() { - return "EthereumBlockHeaderAttestation(" + this.height + ")"; - } - - @Override - public int compareTo(TimeAttestation o) { - EthereumBlockHeaderAttestation ob = (EthereumBlockHeaderAttestation) o; - - return this.height - ob.height; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof EthereumBlockHeaderAttestation)) { - return false; - } - - if (!Arrays.equals(this._TAG(), ((EthereumBlockHeaderAttestation) obj)._TAG())) { - return false; - } - - if (this.height != ((EthereumBlockHeaderAttestation) obj).height) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - return Arrays.hashCode(this._TAG()) ^ this.height; - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/LitecoinBlockHeaderAttestation.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/LitecoinBlockHeaderAttestation.java deleted file mode 100644 index dc7c22f28..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/LitecoinBlockHeaderAttestation.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.attestation; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.BlockHeader; -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamSerializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.VerificationException; - -import java.util.Arrays; - -/** - * Litecoin Block Header Attestation. - * - * @see TimeAttestation - */ -public class LitecoinBlockHeaderAttestation extends TimeAttestation { - - public static byte[] _TAG = {(byte) 0x06, (byte) 0x86, (byte) 0x9a, (byte) 0x0d, (byte) 0x73, (byte) 0xd7, (byte) 0x1b, (byte) 0x45}; - - public static String chain = "litecoin"; - - @Override - public byte[] _TAG() { - return LitecoinBlockHeaderAttestation._TAG; - } - - private int height = 0; - - public int getHeight() { - return height; - } - - public LitecoinBlockHeaderAttestation(int height_) { - super(); - this.height = height_; - } - - public static LitecoinBlockHeaderAttestation deserialize(StreamDeserializationContext ctxPayload) { - int height = ctxPayload.readVaruint(); - - return new LitecoinBlockHeaderAttestation(height); - } - - @Override - public void serializePayload(StreamSerializationContext ctx) { - ctx.writeVaruint(this.height); - } - - public String toString() { - return "LitecoinBlockHeaderAttestation(" + this.height + ")"; - } - - @Override - public int compareTo(TimeAttestation o) { - LitecoinBlockHeaderAttestation ob = (LitecoinBlockHeaderAttestation) o; - - return this.height - ob.height; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof LitecoinBlockHeaderAttestation)) { - return false; - } - - if (!Arrays.equals(this._TAG(), ((LitecoinBlockHeaderAttestation) obj)._TAG())) { - return false; - } - - if (this.height != ((LitecoinBlockHeaderAttestation) obj).height) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - return Arrays.hashCode(this._TAG()) ^ this.height; - } - - /** - * Verify attestation against a Litecoin block header. - * @param digest the digest - * @param block the Litecoin block header - * @return the block time on success; raises VerificationError on failure. - * @throws VerificationException verification exception - */ - public Long verifyAgainstBlockheader(byte[] digest, BlockHeader block) throws VerificationException { - if (digest.length != 32) { - throw new VerificationException("Expected digest with length 32 bytes; got " + digest.length + " bytes"); - } else if (!Arrays.equals(digest, Utils.hexToBytes(block.getMerkleroot()))) { - throw new VerificationException("Digest does not match merkleroot"); - } - - return block.getTime(); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/PendingAttestation.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/PendingAttestation.java deleted file mode 100644 index 93c0e26e6..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/PendingAttestation.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.attestation; - -import android.util.Log; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamSerializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException; - -import java.nio.charset.StandardCharsets; -import java.util.Arrays; - -/** - * Pending attestations. - * Commitment has been recorded in a remote calendar for future attestation, - * and we have a URI to find a more complete timestamp in the future. - * Nothing other than the URI is recorded, nor is there provision made to add - * extra metadata (other than the URI) in future upgrades. The rational here - * is that remote calendars promise to keep commitments indefinitely, so from - * the moment they are created it should be possible to find the commitment in - * the calendar. Thus if you're not satisfied with the local verifiability of - * a timestamp, the correct thing to do is just ask the remote calendar if - * additional attestations are available and/or when they'll be available. - * While we could additional metadata like what types of attestations the - * remote calendar expects to be able to provide in the future, that metadata - * can easily change in the future too. Given that we don't expect timestamps - * to normally have more than a small number of remote calendar attestations, - * it'd be better to have verifiers get the most recent status of such - * information (possibly with appropriate negative response caching). - * - * @see TimeAttestation - */ -public class PendingAttestation extends TimeAttestation { - - public static byte[] _TAG = {(byte) 0x83, (byte) 0xdf, (byte) 0xe3, (byte) 0x0d, (byte) 0x2e, (byte) 0xf9, (byte) 0x0c, (byte) 0x8e}; - - @Override - public byte[] _TAG() { - return PendingAttestation._TAG; - } - - public static int _MAX_URI_LENGTH = 1000; - - public static String _ALLOWED_URI_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._/:"; - - private byte[] uri; - - public byte[] getUri() { - return uri; - } - - public PendingAttestation(byte[] uri_) { - super(); - this.uri = uri_; - } - - public static boolean checkUri(byte[] uri) { - if (uri.length > PendingAttestation._MAX_URI_LENGTH) { - System.err.print("URI exceeds maximum length"); - - return false; - } - - for (int i = 0; i < uri.length; i++) { - Character c = String.format("%c", uri[i]).charAt(0); - - if (PendingAttestation._ALLOWED_URI_CHARS.indexOf(c) < 0) { - Log.e("OpenTimestamp","URI contains invalid character "); - - return false; - } - } - - return true; - } - - public static PendingAttestation deserialize(StreamDeserializationContext ctxPayload) - throws DeserializationException { - - byte[] utf8Uri; - try { - utf8Uri = ctxPayload.readVarbytes(PendingAttestation._MAX_URI_LENGTH); - } catch (DeserializationException e) { - Log.e("OpenTimestamp","URI too long and thus invalid: "); - throw new DeserializationException("Invalid URI: "); - } - - if (PendingAttestation.checkUri(utf8Uri) == false) { - Log.e("OpenTimestamp","Invalid URI: "); - throw new DeserializationException("Invalid URI: "); - } - - return new PendingAttestation(utf8Uri); - } - - @Override - public void serializePayload(StreamSerializationContext ctx) { - ctx.writeVarbytes(this.uri); - } - - public String toString() { - return "PendingAttestation(\'" + new String(this.uri, StandardCharsets.UTF_8) + "\')"; - } - - @Override - public int compareTo(TimeAttestation o) { - PendingAttestation opa = (PendingAttestation) o; - - return Utils.compare(this.uri, opa.uri); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof PendingAttestation)) { - return false; - } - - if (!Arrays.equals(this._TAG(), ((PendingAttestation) obj)._TAG())) { - return false; - } - - if (!Arrays.equals(this.uri, ((PendingAttestation) obj).uri)) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - return Arrays.hashCode(this._TAG()) ^ Arrays.hashCode(this.uri); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/TimeAttestation.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/TimeAttestation.java deleted file mode 100644 index 2f511f8b5..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/TimeAttestation.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.attestation; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamSerializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.Timestamp; -import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException; - -import java.util.Arrays; - -/** - * Class representing {@link Timestamp} signature verification - */ -public abstract class TimeAttestation implements Comparable { - - public static int _TAG_SIZE = 8; - - public static int _MAX_PAYLOAD_SIZE = 8192; - - public byte[] _TAG; - - public byte[] _TAG() { - return new byte[]{}; - } - - /** - * Deserialize a general Time Attestation to the specific subclass Attestation. - * - * @param ctx The stream deserialization context. - * @return The specific subclass Attestation. - */ - public static TimeAttestation deserialize(StreamDeserializationContext ctx) throws DeserializationException { - // console.log('attestation deserialize'); - - byte[] tag = ctx.readBytes(_TAG_SIZE); - // console.log('tag: ', com.vitorpamplona.quartz.ots.Utils.bytesToHex(tag)); - - byte[] serializedAttestation = ctx.readVarbytes(_MAX_PAYLOAD_SIZE); - // console.log('serializedAttestation: ', com.vitorpamplona.quartz.ots.Utils.bytesToHex(serializedAttestation)); - - StreamDeserializationContext ctxPayload = new StreamDeserializationContext(serializedAttestation); - - /* eslint no-use-before-define: ["error", { "classes": false }] */ - if (Arrays.equals(tag, PendingAttestation._TAG) == true) { - return PendingAttestation.deserialize(ctxPayload); - } else if (Arrays.equals(tag, BitcoinBlockHeaderAttestation._TAG) == true) { - return BitcoinBlockHeaderAttestation.deserialize(ctxPayload); - } else if (Arrays.equals(tag, LitecoinBlockHeaderAttestation._TAG) == true) { - return LitecoinBlockHeaderAttestation.deserialize(ctxPayload); - } else if (Arrays.equals(tag, EthereumBlockHeaderAttestation._TAG) == true) { - return EthereumBlockHeaderAttestation.deserialize(ctxPayload); - } - - return new UnknownAttestation(tag, serializedAttestation); - } - - /** - * Serialize a a general Time Attestation to the specific subclass Attestation. - * - * @param ctx The output stream serialization context. - */ - public void serialize(StreamSerializationContext ctx) { - ctx.writeBytes(this._TAG()); - StreamSerializationContext ctxPayload = new StreamSerializationContext(); - serializePayload(ctxPayload); - ctx.writeVarbytes(ctxPayload.getOutput()); - } - - public void serializePayload(StreamSerializationContext ctxPayload) { - // TODO: Is this intentional? - } - - @Override - public int compareTo(TimeAttestation o) { - int deltaTag = Utils.compare(this._TAG(), o._TAG()); - - if (deltaTag == 0) { - return this.compareTo(o); - } else { - return deltaTag; - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/UnknownAttestation.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/UnknownAttestation.java deleted file mode 100644 index 2f726a2d1..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/attestation/UnknownAttestation.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.attestation; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamSerializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException; - -import java.util.Arrays; - -/** - * Placeholder for attestations that don't support - * - * @see TimeAttestation - */ -public class UnknownAttestation extends TimeAttestation { - - byte[] payload; - - public static byte[] _TAG = new byte[]{}; - - @Override - public byte[] _TAG() { - return _TAG; - } - - UnknownAttestation(byte[] tag, byte[] payload) { - super(); - this._TAG = tag; - this.payload = payload; - } - - @Override - public void serializePayload(StreamSerializationContext ctx) { - ctx.writeBytes(this.payload); - } - - public static UnknownAttestation deserialize(StreamDeserializationContext ctxPayload, byte[] tag) throws DeserializationException { - byte[] payload = ctxPayload.readVarbytes(_MAX_PAYLOAD_SIZE); - - return new UnknownAttestation(tag, payload); - } - - public String toString() { - return "UnknownAttestation " + Utils.bytesToHex(this._TAG()) + ' ' + Utils.bytesToHex(this.payload); - } - - @Override - public int compareTo(TimeAttestation o) { - UnknownAttestation ota = (UnknownAttestation) o; - - return Utils.compare(this.payload, ota.payload); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof UnknownAttestation)) { - return false; - } - - if (!Arrays.equals(this._TAG(), ((UnknownAttestation) obj)._TAG())) { - return false; - } - - if (!Arrays.equals(this.payload, ((UnknownAttestation) obj).payload)) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - return Arrays.hashCode(this._TAG()) ^ Arrays.hashCode(this.payload); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Digest.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Digest.java deleted file mode 100644 index 03f47a14a..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Digest.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.crypto; - -/** - * Message digest interface - */ -public interface Digest { - /** - * Return the algorithm name - * - * @return the algorithm name - */ - public String getAlgorithmName(); - - /** - * Return the size, in bytes, of the digest produced by this message digest. - * - * @return the size, in bytes, of the digest produced by this message digest. - */ - public int getDigestSize(); - - /** - * Update the message digest with a single byte. - * - * @param in the input byte to be entered. - */ - public void update(byte in); - - /** - * Update the message digest with a block of bytes. - * - * @param in the byte array containing the data. - * @param inOff the offset into the byte array where the data starts. - * @param len the length of the data. - */ - public void update(byte[] in, int inOff, int len); - - /** - * Close the digest, producing the final digest value. The doFinal - * call also resets the digest. - * - * @param out the array the digest is to be copied into. - * @param outOff the offset into the out array the digest is to start at. - * @return something - * @see #reset() - */ - public int doFinal(byte[] out, int outOff); - - /** - * Reset the digest back to it's initial state. - */ - public void reset(); -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/ExtendedDigest.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/ExtendedDigest.java deleted file mode 100644 index ed3b81563..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/ExtendedDigest.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.crypto; - -public interface ExtendedDigest extends Digest { - /** - * Return the size in bytes of the internal buffer the digest applies it's compression - * function to. - * - * @return byte length of the digests internal buffer. - */ - public int getByteLength(); -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/GeneralDigest.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/GeneralDigest.java deleted file mode 100644 index 284d03653..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/GeneralDigest.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.crypto; - -/** - * Base implementation of MD4 family style digest as outlined in - * "Handbook of Applied Cryptography", pages 344 - 347. - */ -public abstract class GeneralDigest implements ExtendedDigest, Memoable { - - private static final int BYTE_LENGTH = 64; - - private final byte[] xBuf = new byte[4]; - private int xBufOff; - - private long byteCount; - - /** - * Standard constructor - */ - protected GeneralDigest() { - xBufOff = 0; - } - - /** - * Copy constructor. We are using copy constructors in place - * of the Object.clone() interface as this interface is not - * supported by J2ME. - * - * @param t the GeneralDigest - */ - protected GeneralDigest(GeneralDigest t) { - copyIn(t); - } - - protected GeneralDigest(byte[] encodedState) { - System.arraycopy(encodedState, 0, xBuf, 0, xBuf.length); - xBufOff = Pack.bigEndianToInt(encodedState, 4); - byteCount = Pack.bigEndianToLong(encodedState, 8); - } - - protected void copyIn(GeneralDigest t) { - System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length); - - xBufOff = t.xBufOff; - byteCount = t.byteCount; - } - - public void update(byte in) { - xBuf[xBufOff++] = in; - - if (xBufOff == xBuf.length) { - processWord(xBuf, 0); - xBufOff = 0; - } - - byteCount++; - } - - public void update(byte[] in, int inOff, int len) { - len = Math.max(0, len); - - // - // fill the current word - // - int i = 0; - - if (xBufOff != 0) { - while (i < len) { - xBuf[xBufOff++] = in[inOff + i++]; - - if (xBufOff == 4) { - processWord(xBuf, 0); - xBufOff = 0; - break; - } - } - } - - // - // process whole words. - // - int limit = ((len - i) & ~3) + i; - - for (; i < limit; i += 4) { - processWord(in, inOff + i); - } - - // - // load in the remainder. - // - while (i < len) { - xBuf[xBufOff++] = in[inOff + i++]; - } - - byteCount += len; - } - - public void finish() { - long bitLength = (byteCount << 3); - - // - // add the pad bytes. - // - update((byte) 128); - - while (xBufOff != 0) { - update((byte) 0); - } - - processLength(bitLength); - processBlock(); - } - - public void reset() { - byteCount = 0; - - xBufOff = 0; - - for (int i = 0; i < xBuf.length; i++) { - xBuf[i] = 0; - } - } - - protected void populateState(byte[] state) { - System.arraycopy(xBuf, 0, state, 0, xBufOff); - Pack.intToBigEndian(xBufOff, state, 4); - Pack.longToBigEndian(byteCount, state, 8); - } - - public int getByteLength() { - return BYTE_LENGTH; - } - - protected abstract void processWord(byte[] in, int inOff); - - protected abstract void processLength(long bitLength); - - protected abstract void processBlock(); -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/KeccakDigest.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/KeccakDigest.java deleted file mode 100644 index cd669e1ef..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/KeccakDigest.java +++ /dev/null @@ -1,473 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.crypto; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils; - -/** - * Implementation of Keccak based on following KeccakNISTInterface.c from http://keccak.noekeon.org/ - *

- * Following the naming conventions used in the C source code to enable easy review of the implementation. - */ -public class KeccakDigest implements ExtendedDigest { - - private static long[] KeccakRoundConstants = keccakInitializeRoundConstants(); - - private static int[] KeccakRhoOffsets = keccakInitializeRhoOffsets(); - - private static long[] keccakInitializeRoundConstants() { - long[] keccakRoundConstants = new long[24]; - byte[] LFSRstate = new byte[1]; - - LFSRstate[0] = 0x01; - int i, j, bitPosition; - - for (i = 0; i < 24; i++) { - keccakRoundConstants[i] = 0; - - for (j = 0; j < 7; j++) { - bitPosition = (1 << j) - 1; - - if (LFSR86540(LFSRstate)) { - keccakRoundConstants[i] ^= 1L << bitPosition; - } - } - } - - return keccakRoundConstants; - } - - private static boolean LFSR86540(byte[] LFSR) { - boolean result = (((LFSR[0]) & 0x01) != 0); - - if (((LFSR[0]) & 0x80) != 0) { - LFSR[0] = (byte) (((LFSR[0]) << 1) ^ 0x71); - } else { - LFSR[0] <<= 1; - } - - return result; - } - - private static int[] keccakInitializeRhoOffsets() { - int[] keccakRhoOffsets = new int[25]; - int x, y, t, newX, newY; - - keccakRhoOffsets[(((0) % 5) + 5 * ((0) % 5))] = 0; - x = 1; - y = 0; - - for (t = 0; t < 24; t++) { - keccakRhoOffsets[(((x) % 5) + 5 * ((y) % 5))] = ((t + 1) * (t + 2) / 2) % 64; - newX = (0 * x + 1 * y) % 5; - newY = (2 * x + 3 * y) % 5; - x = newX; - y = newY; - } - - return keccakRhoOffsets; - } - - protected byte[] state = new byte[(1600 / 8)]; - protected byte[] dataQueue = new byte[(1536 / 8)]; - protected int rate; - protected int bitsInQueue; - protected int fixedOutputLength; - protected boolean squeezing; - protected int bitsAvailableForSqueezing; - protected byte[] chunk; - protected byte[] oneByte; - - private void clearDataQueueSection(int off, int len) { - for (int i = off; i != off + len; i++) { - dataQueue[i] = 0; - } - } - - public KeccakDigest() { - this(288); - } - - public KeccakDigest(int bitLength) { - init(bitLength); - } - - public KeccakDigest(KeccakDigest source) { - System.arraycopy(source.state, 0, this.state, 0, source.state.length); - System.arraycopy(source.dataQueue, 0, this.dataQueue, 0, source.dataQueue.length); - this.rate = source.rate; - this.bitsInQueue = source.bitsInQueue; - this.fixedOutputLength = source.fixedOutputLength; - this.squeezing = source.squeezing; - this.bitsAvailableForSqueezing = source.bitsAvailableForSqueezing; - this.chunk = Utils.arraysCopy(source.chunk); - this.oneByte = Utils.arraysCopy(source.oneByte); - } - - public String getAlgorithmName() { - return "Keccak-" + fixedOutputLength; - } - - public int getDigestSize() { - return fixedOutputLength / 8; - } - - public void update(byte in) { - oneByte[0] = in; - - absorb(oneByte, 0, 8L); - } - - public void update(byte[] in, int inOff, int len) { - absorb(in, inOff, len * 8L); - } - - public int doFinal(byte[] out, int outOff) { - squeeze(out, outOff, fixedOutputLength); - reset(); - - return getDigestSize(); - } - - /* - * TODO Possible API change to support partial-byte suffixes. - */ - protected int doFinal(byte[] out, int outOff, byte partialByte, int partialBits) { - if (partialBits > 0) { - oneByte[0] = partialByte; - absorb(oneByte, 0, partialBits); - } - - squeeze(out, outOff, fixedOutputLength); - reset(); - - return getDigestSize(); - } - - public void reset() { - init(fixedOutputLength); - } - - /** - * Return the size of block that the compression function is applied to in bytes. - * - * @return internal byte length of a block. - */ - public int getByteLength() { - return rate / 8; - } - - private void init(int bitLength) { - switch (bitLength) { - case 288: - initSponge(1024, 576); - break; - case 128: - initSponge(1344, 256); - break; - case 224: - initSponge(1152, 448); - break; - case 256: - initSponge(1088, 512); - break; - case 384: - initSponge(832, 768); - break; - case 512: - initSponge(576, 1024); - break; - default: - throw new IllegalArgumentException("bitLength must be one of 128, 224, 256, 288, 384, or 512."); - } - } - - private void initSponge(int rate, int capacity) { - if (rate + capacity != 1600) { - throw new IllegalStateException("rate + capacity != 1600"); - } - - if ((rate <= 0) || (rate >= 1600) || ((rate % 64) != 0)) { - throw new IllegalStateException("invalid rate value"); - } - - this.rate = rate; - // this is never read, need to check to see why we want to save it - // this.capacity = capacity; - Utils.arrayFill(this.state, (byte) 0); - Utils.arrayFill(this.dataQueue, (byte) 0); - this.bitsInQueue = 0; - this.squeezing = false; - this.bitsAvailableForSqueezing = 0; - this.fixedOutputLength = capacity / 2; - this.chunk = new byte[rate / 8]; - this.oneByte = new byte[1]; - } - - private void absorbQueue() { - KeccakAbsorb(state, dataQueue, rate / 8); - bitsInQueue = 0; - } - - protected void absorb(byte[] data, int off, long databitlen) { - long i, j, wholeBlocks; - - if ((bitsInQueue % 8) != 0) { - throw new IllegalStateException("attempt to absorb with odd length queue"); - } - - if (squeezing) { - throw new IllegalStateException("attempt to absorb while squeezing"); - } - - i = 0; - - while (i < databitlen) { - if ((bitsInQueue == 0) && (databitlen >= rate) && (i <= (databitlen - rate))) { - wholeBlocks = (databitlen - i) / rate; - - for (j = 0; j < wholeBlocks; j++) { - System.arraycopy(data, (int) (off + (i / 8) + (j * chunk.length)), chunk, 0, chunk.length); - -// displayIntermediateValues.displayBytes(1, "Block to be absorbed", curData, rate / 8); - - KeccakAbsorb(state, chunk, chunk.length); - } - - i += wholeBlocks * rate; - } else { - int partialBlock = (int) (databitlen - i); - - if (partialBlock + bitsInQueue > rate) { - partialBlock = rate - bitsInQueue; - } - - int partialByte = partialBlock % 8; - partialBlock -= partialByte; - System.arraycopy(data, off + (int) (i / 8), dataQueue, bitsInQueue / 8, partialBlock / 8); - - bitsInQueue += partialBlock; - i += partialBlock; - - if (bitsInQueue == rate) { - absorbQueue(); - } - - if (partialByte > 0) { - int mask = (1 << partialByte) - 1; - dataQueue[bitsInQueue / 8] = (byte) (data[off + ((int) (i / 8))] & mask); - bitsInQueue += partialByte; - i += partialByte; - } - } - } - } - - private void padAndSwitchToSqueezingPhase() { - if (bitsInQueue + 1 == rate) { - dataQueue[bitsInQueue / 8] |= 1 << (bitsInQueue % 8); - absorbQueue(); - clearDataQueueSection(0, rate / 8); - } else { - clearDataQueueSection((bitsInQueue + 7) / 8, rate / 8 - (bitsInQueue + 7) / 8); - dataQueue[bitsInQueue / 8] |= 1 << (bitsInQueue % 8); - } - - dataQueue[(rate - 1) / 8] |= 1 << ((rate - 1) % 8); - absorbQueue(); - -// displayIntermediateValues.displayText(1, "--- Switching to squeezing phase ---"); - - if (rate == 1024) { - KeccakExtract1024bits(state, dataQueue); - bitsAvailableForSqueezing = 1024; - } else { - KeccakExtract(state, dataQueue, rate / 64); - bitsAvailableForSqueezing = rate; - } - -// displayIntermediateValues.displayBytes(1, "Block available for squeezing", dataQueue, bitsAvailableForSqueezing / 8); - - squeezing = true; - } - - protected void squeeze(byte[] output, int offset, long outputLength) { - long i; - int partialBlock; - - if (!squeezing) { - padAndSwitchToSqueezingPhase(); - } - - if ((outputLength % 8) != 0) { - throw new IllegalStateException("outputLength not a multiple of 8"); - } - - i = 0; - - while (i < outputLength) { - if (bitsAvailableForSqueezing == 0) { - keccakPermutation(state); - - if (rate == 1024) { - KeccakExtract1024bits(state, dataQueue); - bitsAvailableForSqueezing = 1024; - } else { - KeccakExtract(state, dataQueue, rate / 64); - bitsAvailableForSqueezing = rate; - } - -// displayIntermediateValues.displayBytes(1, "Block available for squeezing", dataQueue, bitsAvailableForSqueezing / 8); - - } - - partialBlock = bitsAvailableForSqueezing; - - if ((long) partialBlock > outputLength - i) { - partialBlock = (int) (outputLength - i); - } - - System.arraycopy(dataQueue, (rate - bitsAvailableForSqueezing) / 8, output, offset + (int) (i / 8), partialBlock / 8); - bitsAvailableForSqueezing -= partialBlock; - i += partialBlock; - } - } - - private void fromBytesToWords(long[] stateAsWords, byte[] state) { - for (int i = 0; i < (1600 / 64); i++) { - stateAsWords[i] = 0; - int index = i * (64 / 8); - - for (int j = 0; j < (64 / 8); j++) { - stateAsWords[i] |= ((long) state[index + j] & 0xff) << ((8 * j)); - } - } - } - - private void fromWordsToBytes(byte[] state, long[] stateAsWords) { - for (int i = 0; i < (1600 / 64); i++) { - int index = i * (64 / 8); - - for (int j = 0; j < (64 / 8); j++) { - state[index + j] = (byte) ((stateAsWords[i] >>> ((8 * j))) & 0xFF); - } - } - } - - private void keccakPermutation(byte[] state) { - long[] longState = new long[state.length / 8]; - - fromBytesToWords(longState, state); - -// displayIntermediateValues.displayStateAsBytes(1, "Input of permutation", longState); - - keccakPermutationOnWords(longState); - -// displayIntermediateValues.displayStateAsBytes(1, "State after permutation", longState); - - fromWordsToBytes(state, longState); - } - - private void keccakPermutationAfterXor(byte[] state, byte[] data, int dataLengthInBytes) { - int i; - - for (i = 0; i < dataLengthInBytes; i++) { - state[i] ^= data[i]; - } - - keccakPermutation(state); - } - - private void keccakPermutationOnWords(long[] state) { - int i; - -// displayIntermediateValues.displayStateAs64bitWords(3, "Same, with lanes as 64-bit words", state); - - for (i = 0; i < 24; i++) { -// displayIntermediateValues.displayRoundNumber(3, i); - - theta(state); -// displayIntermediateValues.displayStateAs64bitWords(3, "After theta", state); - - rho(state); -// displayIntermediateValues.displayStateAs64bitWords(3, "After rho", state); - - pi(state); -// displayIntermediateValues.displayStateAs64bitWords(3, "After pi", state); - - chi(state); -// displayIntermediateValues.displayStateAs64bitWords(3, "After chi", state); - - iota(state, i); -// displayIntermediateValues.displayStateAs64bitWords(3, "After iota", state); - } - } - - long[] C = new long[5]; - - private void theta(long[] A) { - for (int x = 0; x < 5; x++) { - C[x] = 0; - - for (int y = 0; y < 5; y++) { - C[x] ^= A[x + 5 * y]; - } - } - for (int x = 0; x < 5; x++) { - long dX = ((((C[(x + 1) % 5]) << 1) ^ ((C[(x + 1) % 5]) >>> (64 - 1)))) ^ C[(x + 4) % 5]; - - for (int y = 0; y < 5; y++) { - A[x + 5 * y] ^= dX; - } - } - } - - private void rho(long[] A) { - for (int x = 0; x < 5; x++) { - for (int y = 0; y < 5; y++) { - int index = x + 5 * y; - A[index] = ((KeccakRhoOffsets[index] != 0) ? (((A[index]) << KeccakRhoOffsets[index]) ^ ((A[index]) >>> (64 - KeccakRhoOffsets[index]))) : A[index]); - } - } - } - - long[] tempA = new long[25]; - - private void pi(long[] A) { - System.arraycopy(A, 0, tempA, 0, tempA.length); - - for (int x = 0; x < 5; x++) { - for (int y = 0; y < 5; y++) { - A[y + 5 * ((2 * x + 3 * y) % 5)] = tempA[x + 5 * y]; - } - } - } - - long[] chiC = new long[5]; - - private void chi(long[] A) { - for (int y = 0; y < 5; y++) { - for (int x = 0; x < 5; x++) { - chiC[x] = A[x + 5 * y] ^ ((~A[(((x + 1) % 5) + 5 * y)]) & A[(((x + 2) % 5) + 5 * y)]); - } - - for (int x = 0; x < 5; x++) { - A[x + 5 * y] = chiC[x]; - } - } - } - - private void iota(long[] A, int indexRound) { - A[(((0) % 5) + 5 * ((0) % 5))] ^= KeccakRoundConstants[indexRound]; - } - - private void KeccakAbsorb(byte[] byteState, byte[] data, int dataInBytes) { - keccakPermutationAfterXor(byteState, data, dataInBytes); - } - - private void KeccakExtract1024bits(byte[] byteState, byte[] data) { - System.arraycopy(byteState, 0, data, 0, 128); - } - - private void KeccakExtract(byte[] byteState, byte[] data, int laneCount) { - System.arraycopy(byteState, 0, data, 0, laneCount * 8); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Memoable.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Memoable.java deleted file mode 100644 index 59b8154a8..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Memoable.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.crypto; - -/** - * Interface for Memoable objects. Memoable objects allow the taking of a snapshot of their internal state - * via the {@link #copy copy()} method and then resetting the object back to that state later using the - * {@link #reset reset()} method. - */ -public interface Memoable { - /** - * Produce a copy of this object with its configuration and in its current state. - *

- * The returned object may be used simply to store the state, or may be used as a similar object - * starting from the copied state. - * - * @return Memoable object - */ - Memoable copy(); - - /** - * Restore a copied object state into this object. - *

- * Implementations of this method should try to avoid or minimise memory allocation to perform the reset. - * - * @param other an object originally {@link #copy() copied} from an object of the same type as this instance. - * @throws ClassCastException if the provided object is not of the correct type. - */ - void reset(Memoable other); -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Pack.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Pack.java deleted file mode 100644 index 7fe7a0ce3..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/Pack.java +++ /dev/null @@ -1,242 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.crypto; - -/** - * Utility methods for converting byte arrays into ints and longs, and back again. - */ -public abstract class Pack -{ - public static short bigEndianToShort(byte[] bs, int off) - { - int n = (bs[ off] & 0xff) << 8; - n |= (bs[++off] & 0xff); - return (short)n; - } - - public static int bigEndianToInt(byte[] bs, int off) - { - int n = bs[ off] << 24; - n |= (bs[++off] & 0xff) << 16; - n |= (bs[++off] & 0xff) << 8; - n |= (bs[++off] & 0xff); - return n; - } - - public static void bigEndianToInt(byte[] bs, int off, int[] ns) - { - for (int i = 0; i < ns.length; ++i) - { - ns[i] = bigEndianToInt(bs, off); - off += 4; - } - } - - public static byte[] intToBigEndian(int n) - { - byte[] bs = new byte[4]; - intToBigEndian(n, bs, 0); - return bs; - } - - public static void intToBigEndian(int n, byte[] bs, int off) - { - bs[ off] = (byte)(n >>> 24); - bs[++off] = (byte)(n >>> 16); - bs[++off] = (byte)(n >>> 8); - bs[++off] = (byte)(n ); - } - - public static byte[] intToBigEndian(int[] ns) - { - byte[] bs = new byte[4 * ns.length]; - intToBigEndian(ns, bs, 0); - return bs; - } - - public static void intToBigEndian(int[] ns, byte[] bs, int off) - { - for (int i = 0; i < ns.length; ++i) - { - intToBigEndian(ns[i], bs, off); - off += 4; - } - } - - public static long bigEndianToLong(byte[] bs, int off) - { - int hi = bigEndianToInt(bs, off); - int lo = bigEndianToInt(bs, off + 4); - return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL); - } - - public static void bigEndianToLong(byte[] bs, int off, long[] ns) - { - for (int i = 0; i < ns.length; ++i) - { - ns[i] = bigEndianToLong(bs, off); - off += 8; - } - } - - public static byte[] longToBigEndian(long n) - { - byte[] bs = new byte[8]; - longToBigEndian(n, bs, 0); - return bs; - } - - public static void longToBigEndian(long n, byte[] bs, int off) - { - intToBigEndian((int)(n >>> 32), bs, off); - intToBigEndian((int)(n & 0xffffffffL), bs, off + 4); - } - - public static byte[] longToBigEndian(long[] ns) - { - byte[] bs = new byte[8 * ns.length]; - longToBigEndian(ns, bs, 0); - return bs; - } - - public static void longToBigEndian(long[] ns, byte[] bs, int off) - { - for (int i = 0; i < ns.length; ++i) - { - longToBigEndian(ns[i], bs, off); - off += 8; - } - } - - public static short littleEndianToShort(byte[] bs, int off) - { - int n = bs[ off] & 0xff; - n |= (bs[++off] & 0xff) << 8; - return (short)n; - } - - public static int littleEndianToInt(byte[] bs, int off) - { - int n = bs[ off] & 0xff; - n |= (bs[++off] & 0xff) << 8; - n |= (bs[++off] & 0xff) << 16; - n |= bs[++off] << 24; - return n; - } - - public static void littleEndianToInt(byte[] bs, int off, int[] ns) - { - for (int i = 0; i < ns.length; ++i) - { - ns[i] = littleEndianToInt(bs, off); - off += 4; - } - } - - public static void littleEndianToInt(byte[] bs, int bOff, int[] ns, int nOff, int count) - { - for (int i = 0; i < count; ++i) - { - ns[nOff + i] = littleEndianToInt(bs, bOff); - bOff += 4; - } - } - - public static int[] littleEndianToInt(byte[] bs, int off, int count) - { - int[] ns = new int[count]; - for (int i = 0; i < ns.length; ++i) - { - ns[i] = littleEndianToInt(bs, off); - off += 4; - } - return ns; - } - - public static byte[] shortToLittleEndian(short n) - { - byte[] bs = new byte[2]; - shortToLittleEndian(n, bs, 0); - return bs; - } - - public static void shortToLittleEndian(short n, byte[] bs, int off) - { - bs[ off] = (byte)(n ); - bs[++off] = (byte)(n >>> 8); - } - - public static byte[] intToLittleEndian(int n) - { - byte[] bs = new byte[4]; - intToLittleEndian(n, bs, 0); - return bs; - } - - public static void intToLittleEndian(int n, byte[] bs, int off) - { - bs[ off] = (byte)(n ); - bs[++off] = (byte)(n >>> 8); - bs[++off] = (byte)(n >>> 16); - bs[++off] = (byte)(n >>> 24); - } - - public static byte[] intToLittleEndian(int[] ns) - { - byte[] bs = new byte[4 * ns.length]; - intToLittleEndian(ns, bs, 0); - return bs; - } - - public static void intToLittleEndian(int[] ns, byte[] bs, int off) - { - for (int i = 0; i < ns.length; ++i) - { - intToLittleEndian(ns[i], bs, off); - off += 4; - } - } - - public static long littleEndianToLong(byte[] bs, int off) - { - int lo = littleEndianToInt(bs, off); - int hi = littleEndianToInt(bs, off + 4); - return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL); - } - - public static void littleEndianToLong(byte[] bs, int off, long[] ns) - { - for (int i = 0; i < ns.length; ++i) - { - ns[i] = littleEndianToLong(bs, off); - off += 8; - } - } - - public static byte[] longToLittleEndian(long n) - { - byte[] bs = new byte[8]; - longToLittleEndian(n, bs, 0); - return bs; - } - - public static void longToLittleEndian(long n, byte[] bs, int off) - { - intToLittleEndian((int)(n & 0xffffffffL), bs, off); - intToLittleEndian((int)(n >>> 32), bs, off + 4); - } - - public static byte[] longToLittleEndian(long[] ns) - { - byte[] bs = new byte[8 * ns.length]; - longToLittleEndian(ns, bs, 0); - return bs; - } - - public static void longToLittleEndian(long[] ns, byte[] bs, int off) - { - for (int i = 0; i < ns.length; ++i) - { - longToLittleEndian(ns[i], bs, off); - off += 8; - } - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/RIPEMD160Digest.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/RIPEMD160Digest.java deleted file mode 100644 index d50e65ab6..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/crypto/RIPEMD160Digest.java +++ /dev/null @@ -1,442 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.crypto; - -/** - * Implementation of RIPEMD - * - * @see ripemd160 - */ -public class RIPEMD160Digest - extends GeneralDigest -{ - private static final int DIGEST_LENGTH = 20; - - private int H0, H1, H2, H3, H4; // IV's - - private int[] X = new int[16]; - private int xOff; - - /** - * Standard constructor - */ - public RIPEMD160Digest() - { - reset(); - } - - /** - * Copy constructor. This will copy the state of the provided - * message digest. - * @param t RIPEMD160Digest - */ - public RIPEMD160Digest(RIPEMD160Digest t) - { - super(t); - - copyIn(t); - } - - private void copyIn(RIPEMD160Digest t) - { - super.copyIn(t); - - H0 = t.H0; - H1 = t.H1; - H2 = t.H2; - H3 = t.H3; - H4 = t.H4; - - System.arraycopy(t.X, 0, X, 0, t.X.length); - xOff = t.xOff; - } - - public String getAlgorithmName() - { - return "RIPEMD160"; - } - - public int getDigestSize() - { - return DIGEST_LENGTH; - } - - protected void processWord( - byte[] in, - int inOff) - { - X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8) - | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); - - if (xOff == 16) - { - processBlock(); - } - } - - protected void processLength( - long bitLength) - { - if (xOff > 14) - { - processBlock(); - } - - X[14] = (int)(bitLength & 0xffffffff); - X[15] = (int)(bitLength >>> 32); - } - - private void unpackWord( - int word, - byte[] out, - int outOff) - { - out[outOff] = (byte)word; - out[outOff + 1] = (byte)(word >>> 8); - out[outOff + 2] = (byte)(word >>> 16); - out[outOff + 3] = (byte)(word >>> 24); - } - - public int doFinal( - byte[] out, - int outOff) - { - finish(); - - unpackWord(H0, out, outOff); - unpackWord(H1, out, outOff + 4); - unpackWord(H2, out, outOff + 8); - unpackWord(H3, out, outOff + 12); - unpackWord(H4, out, outOff + 16); - - reset(); - - return DIGEST_LENGTH; - } - - /** - * reset the chaining variables to the IV values. - */ - public void reset() - { - super.reset(); - - H0 = 0x67452301; - H1 = 0xefcdab89; - H2 = 0x98badcfe; - H3 = 0x10325476; - H4 = 0xc3d2e1f0; - - xOff = 0; - - for (int i = 0; i != X.length; i++) - { - X[i] = 0; - } - } - - /* - * rotate int x left n bits. - */ - private int RL( - int x, - int n) - { - return (x << n) | (x >>> (32 - n)); - } - - /* - * f1,f2,f3,f4,f5 are the basic RIPEMD160 functions. - */ - - /* - * rounds 0-15 - */ - private int f1( - int x, - int y, - int z) - { - return x ^ y ^ z; - } - - /* - * rounds 16-31 - */ - private int f2( - int x, - int y, - int z) - { - return (x & y) | (~x & z); - } - - /* - * rounds 32-47 - */ - private int f3( - int x, - int y, - int z) - { - return (x | ~y) ^ z; - } - - /* - * rounds 48-63 - */ - private int f4( - int x, - int y, - int z) - { - return (x & z) | (y & ~z); - } - - /* - * rounds 64-79 - */ - private int f5( - int x, - int y, - int z) - { - return x ^ (y | ~z); - } - - protected void processBlock() - { - int a, aa; - int b, bb; - int c, cc; - int d, dd; - int e, ee; - - a = aa = H0; - b = bb = H1; - c = cc = H2; - d = dd = H3; - e = ee = H4; - - // - // Rounds 1 - 16 - // - // left - a = RL(a + f1(b,c,d) + X[ 0], 11) + e; c = RL(c, 10); - e = RL(e + f1(a,b,c) + X[ 1], 14) + d; b = RL(b, 10); - d = RL(d + f1(e,a,b) + X[ 2], 15) + c; a = RL(a, 10); - c = RL(c + f1(d,e,a) + X[ 3], 12) + b; e = RL(e, 10); - b = RL(b + f1(c,d,e) + X[ 4], 5) + a; d = RL(d, 10); - a = RL(a + f1(b,c,d) + X[ 5], 8) + e; c = RL(c, 10); - e = RL(e + f1(a,b,c) + X[ 6], 7) + d; b = RL(b, 10); - d = RL(d + f1(e,a,b) + X[ 7], 9) + c; a = RL(a, 10); - c = RL(c + f1(d,e,a) + X[ 8], 11) + b; e = RL(e, 10); - b = RL(b + f1(c,d,e) + X[ 9], 13) + a; d = RL(d, 10); - a = RL(a + f1(b,c,d) + X[10], 14) + e; c = RL(c, 10); - e = RL(e + f1(a,b,c) + X[11], 15) + d; b = RL(b, 10); - d = RL(d + f1(e,a,b) + X[12], 6) + c; a = RL(a, 10); - c = RL(c + f1(d,e,a) + X[13], 7) + b; e = RL(e, 10); - b = RL(b + f1(c,d,e) + X[14], 9) + a; d = RL(d, 10); - a = RL(a + f1(b,c,d) + X[15], 8) + e; c = RL(c, 10); - - // right - aa = RL(aa + f5(bb,cc,dd) + X[ 5] + 0x50a28be6, 8) + ee; cc = RL(cc, 10); - ee = RL(ee + f5(aa,bb,cc) + X[14] + 0x50a28be6, 9) + dd; bb = RL(bb, 10); - dd = RL(dd + f5(ee,aa,bb) + X[ 7] + 0x50a28be6, 9) + cc; aa = RL(aa, 10); - cc = RL(cc + f5(dd,ee,aa) + X[ 0] + 0x50a28be6, 11) + bb; ee = RL(ee, 10); - bb = RL(bb + f5(cc,dd,ee) + X[ 9] + 0x50a28be6, 13) + aa; dd = RL(dd, 10); - aa = RL(aa + f5(bb,cc,dd) + X[ 2] + 0x50a28be6, 15) + ee; cc = RL(cc, 10); - ee = RL(ee + f5(aa,bb,cc) + X[11] + 0x50a28be6, 15) + dd; bb = RL(bb, 10); - dd = RL(dd + f5(ee,aa,bb) + X[ 4] + 0x50a28be6, 5) + cc; aa = RL(aa, 10); - cc = RL(cc + f5(dd,ee,aa) + X[13] + 0x50a28be6, 7) + bb; ee = RL(ee, 10); - bb = RL(bb + f5(cc,dd,ee) + X[ 6] + 0x50a28be6, 7) + aa; dd = RL(dd, 10); - aa = RL(aa + f5(bb,cc,dd) + X[15] + 0x50a28be6, 8) + ee; cc = RL(cc, 10); - ee = RL(ee + f5(aa,bb,cc) + X[ 8] + 0x50a28be6, 11) + dd; bb = RL(bb, 10); - dd = RL(dd + f5(ee,aa,bb) + X[ 1] + 0x50a28be6, 14) + cc; aa = RL(aa, 10); - cc = RL(cc + f5(dd,ee,aa) + X[10] + 0x50a28be6, 14) + bb; ee = RL(ee, 10); - bb = RL(bb + f5(cc,dd,ee) + X[ 3] + 0x50a28be6, 12) + aa; dd = RL(dd, 10); - aa = RL(aa + f5(bb,cc,dd) + X[12] + 0x50a28be6, 6) + ee; cc = RL(cc, 10); - - // - // Rounds 16-31 - // - // left - e = RL(e + f2(a,b,c) + X[ 7] + 0x5a827999, 7) + d; b = RL(b, 10); - d = RL(d + f2(e,a,b) + X[ 4] + 0x5a827999, 6) + c; a = RL(a, 10); - c = RL(c + f2(d,e,a) + X[13] + 0x5a827999, 8) + b; e = RL(e, 10); - b = RL(b + f2(c,d,e) + X[ 1] + 0x5a827999, 13) + a; d = RL(d, 10); - a = RL(a + f2(b,c,d) + X[10] + 0x5a827999, 11) + e; c = RL(c, 10); - e = RL(e + f2(a,b,c) + X[ 6] + 0x5a827999, 9) + d; b = RL(b, 10); - d = RL(d + f2(e,a,b) + X[15] + 0x5a827999, 7) + c; a = RL(a, 10); - c = RL(c + f2(d,e,a) + X[ 3] + 0x5a827999, 15) + b; e = RL(e, 10); - b = RL(b + f2(c,d,e) + X[12] + 0x5a827999, 7) + a; d = RL(d, 10); - a = RL(a + f2(b,c,d) + X[ 0] + 0x5a827999, 12) + e; c = RL(c, 10); - e = RL(e + f2(a,b,c) + X[ 9] + 0x5a827999, 15) + d; b = RL(b, 10); - d = RL(d + f2(e,a,b) + X[ 5] + 0x5a827999, 9) + c; a = RL(a, 10); - c = RL(c + f2(d,e,a) + X[ 2] + 0x5a827999, 11) + b; e = RL(e, 10); - b = RL(b + f2(c,d,e) + X[14] + 0x5a827999, 7) + a; d = RL(d, 10); - a = RL(a + f2(b,c,d) + X[11] + 0x5a827999, 13) + e; c = RL(c, 10); - e = RL(e + f2(a,b,c) + X[ 8] + 0x5a827999, 12) + d; b = RL(b, 10); - - // right - ee = RL(ee + f4(aa,bb,cc) + X[ 6] + 0x5c4dd124, 9) + dd; bb = RL(bb, 10); - dd = RL(dd + f4(ee,aa,bb) + X[11] + 0x5c4dd124, 13) + cc; aa = RL(aa, 10); - cc = RL(cc + f4(dd,ee,aa) + X[ 3] + 0x5c4dd124, 15) + bb; ee = RL(ee, 10); - bb = RL(bb + f4(cc,dd,ee) + X[ 7] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10); - aa = RL(aa + f4(bb,cc,dd) + X[ 0] + 0x5c4dd124, 12) + ee; cc = RL(cc, 10); - ee = RL(ee + f4(aa,bb,cc) + X[13] + 0x5c4dd124, 8) + dd; bb = RL(bb, 10); - dd = RL(dd + f4(ee,aa,bb) + X[ 5] + 0x5c4dd124, 9) + cc; aa = RL(aa, 10); - cc = RL(cc + f4(dd,ee,aa) + X[10] + 0x5c4dd124, 11) + bb; ee = RL(ee, 10); - bb = RL(bb + f4(cc,dd,ee) + X[14] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10); - aa = RL(aa + f4(bb,cc,dd) + X[15] + 0x5c4dd124, 7) + ee; cc = RL(cc, 10); - ee = RL(ee + f4(aa,bb,cc) + X[ 8] + 0x5c4dd124, 12) + dd; bb = RL(bb, 10); - dd = RL(dd + f4(ee,aa,bb) + X[12] + 0x5c4dd124, 7) + cc; aa = RL(aa, 10); - cc = RL(cc + f4(dd,ee,aa) + X[ 4] + 0x5c4dd124, 6) + bb; ee = RL(ee, 10); - bb = RL(bb + f4(cc,dd,ee) + X[ 9] + 0x5c4dd124, 15) + aa; dd = RL(dd, 10); - aa = RL(aa + f4(bb,cc,dd) + X[ 1] + 0x5c4dd124, 13) + ee; cc = RL(cc, 10); - ee = RL(ee + f4(aa,bb,cc) + X[ 2] + 0x5c4dd124, 11) + dd; bb = RL(bb, 10); - - // - // Rounds 32-47 - // - // left - d = RL(d + f3(e,a,b) + X[ 3] + 0x6ed9eba1, 11) + c; a = RL(a, 10); - c = RL(c + f3(d,e,a) + X[10] + 0x6ed9eba1, 13) + b; e = RL(e, 10); - b = RL(b + f3(c,d,e) + X[14] + 0x6ed9eba1, 6) + a; d = RL(d, 10); - a = RL(a + f3(b,c,d) + X[ 4] + 0x6ed9eba1, 7) + e; c = RL(c, 10); - e = RL(e + f3(a,b,c) + X[ 9] + 0x6ed9eba1, 14) + d; b = RL(b, 10); - d = RL(d + f3(e,a,b) + X[15] + 0x6ed9eba1, 9) + c; a = RL(a, 10); - c = RL(c + f3(d,e,a) + X[ 8] + 0x6ed9eba1, 13) + b; e = RL(e, 10); - b = RL(b + f3(c,d,e) + X[ 1] + 0x6ed9eba1, 15) + a; d = RL(d, 10); - a = RL(a + f3(b,c,d) + X[ 2] + 0x6ed9eba1, 14) + e; c = RL(c, 10); - e = RL(e + f3(a,b,c) + X[ 7] + 0x6ed9eba1, 8) + d; b = RL(b, 10); - d = RL(d + f3(e,a,b) + X[ 0] + 0x6ed9eba1, 13) + c; a = RL(a, 10); - c = RL(c + f3(d,e,a) + X[ 6] + 0x6ed9eba1, 6) + b; e = RL(e, 10); - b = RL(b + f3(c,d,e) + X[13] + 0x6ed9eba1, 5) + a; d = RL(d, 10); - a = RL(a + f3(b,c,d) + X[11] + 0x6ed9eba1, 12) + e; c = RL(c, 10); - e = RL(e + f3(a,b,c) + X[ 5] + 0x6ed9eba1, 7) + d; b = RL(b, 10); - d = RL(d + f3(e,a,b) + X[12] + 0x6ed9eba1, 5) + c; a = RL(a, 10); - - // right - dd = RL(dd + f3(ee,aa,bb) + X[15] + 0x6d703ef3, 9) + cc; aa = RL(aa, 10); - cc = RL(cc + f3(dd,ee,aa) + X[ 5] + 0x6d703ef3, 7) + bb; ee = RL(ee, 10); - bb = RL(bb + f3(cc,dd,ee) + X[ 1] + 0x6d703ef3, 15) + aa; dd = RL(dd, 10); - aa = RL(aa + f3(bb,cc,dd) + X[ 3] + 0x6d703ef3, 11) + ee; cc = RL(cc, 10); - ee = RL(ee + f3(aa,bb,cc) + X[ 7] + 0x6d703ef3, 8) + dd; bb = RL(bb, 10); - dd = RL(dd + f3(ee,aa,bb) + X[14] + 0x6d703ef3, 6) + cc; aa = RL(aa, 10); - cc = RL(cc + f3(dd,ee,aa) + X[ 6] + 0x6d703ef3, 6) + bb; ee = RL(ee, 10); - bb = RL(bb + f3(cc,dd,ee) + X[ 9] + 0x6d703ef3, 14) + aa; dd = RL(dd, 10); - aa = RL(aa + f3(bb,cc,dd) + X[11] + 0x6d703ef3, 12) + ee; cc = RL(cc, 10); - ee = RL(ee + f3(aa,bb,cc) + X[ 8] + 0x6d703ef3, 13) + dd; bb = RL(bb, 10); - dd = RL(dd + f3(ee,aa,bb) + X[12] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10); - cc = RL(cc + f3(dd,ee,aa) + X[ 2] + 0x6d703ef3, 14) + bb; ee = RL(ee, 10); - bb = RL(bb + f3(cc,dd,ee) + X[10] + 0x6d703ef3, 13) + aa; dd = RL(dd, 10); - aa = RL(aa + f3(bb,cc,dd) + X[ 0] + 0x6d703ef3, 13) + ee; cc = RL(cc, 10); - ee = RL(ee + f3(aa,bb,cc) + X[ 4] + 0x6d703ef3, 7) + dd; bb = RL(bb, 10); - dd = RL(dd + f3(ee,aa,bb) + X[13] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10); - - // - // Rounds 48-63 - // - // left - c = RL(c + f4(d,e,a) + X[ 1] + 0x8f1bbcdc, 11) + b; e = RL(e, 10); - b = RL(b + f4(c,d,e) + X[ 9] + 0x8f1bbcdc, 12) + a; d = RL(d, 10); - a = RL(a + f4(b,c,d) + X[11] + 0x8f1bbcdc, 14) + e; c = RL(c, 10); - e = RL(e + f4(a,b,c) + X[10] + 0x8f1bbcdc, 15) + d; b = RL(b, 10); - d = RL(d + f4(e,a,b) + X[ 0] + 0x8f1bbcdc, 14) + c; a = RL(a, 10); - c = RL(c + f4(d,e,a) + X[ 8] + 0x8f1bbcdc, 15) + b; e = RL(e, 10); - b = RL(b + f4(c,d,e) + X[12] + 0x8f1bbcdc, 9) + a; d = RL(d, 10); - a = RL(a + f4(b,c,d) + X[ 4] + 0x8f1bbcdc, 8) + e; c = RL(c, 10); - e = RL(e + f4(a,b,c) + X[13] + 0x8f1bbcdc, 9) + d; b = RL(b, 10); - d = RL(d + f4(e,a,b) + X[ 3] + 0x8f1bbcdc, 14) + c; a = RL(a, 10); - c = RL(c + f4(d,e,a) + X[ 7] + 0x8f1bbcdc, 5) + b; e = RL(e, 10); - b = RL(b + f4(c,d,e) + X[15] + 0x8f1bbcdc, 6) + a; d = RL(d, 10); - a = RL(a + f4(b,c,d) + X[14] + 0x8f1bbcdc, 8) + e; c = RL(c, 10); - e = RL(e + f4(a,b,c) + X[ 5] + 0x8f1bbcdc, 6) + d; b = RL(b, 10); - d = RL(d + f4(e,a,b) + X[ 6] + 0x8f1bbcdc, 5) + c; a = RL(a, 10); - c = RL(c + f4(d,e,a) + X[ 2] + 0x8f1bbcdc, 12) + b; e = RL(e, 10); - - // right - cc = RL(cc + f2(dd,ee,aa) + X[ 8] + 0x7a6d76e9, 15) + bb; ee = RL(ee, 10); - bb = RL(bb + f2(cc,dd,ee) + X[ 6] + 0x7a6d76e9, 5) + aa; dd = RL(dd, 10); - aa = RL(aa + f2(bb,cc,dd) + X[ 4] + 0x7a6d76e9, 8) + ee; cc = RL(cc, 10); - ee = RL(ee + f2(aa,bb,cc) + X[ 1] + 0x7a6d76e9, 11) + dd; bb = RL(bb, 10); - dd = RL(dd + f2(ee,aa,bb) + X[ 3] + 0x7a6d76e9, 14) + cc; aa = RL(aa, 10); - cc = RL(cc + f2(dd,ee,aa) + X[11] + 0x7a6d76e9, 14) + bb; ee = RL(ee, 10); - bb = RL(bb + f2(cc,dd,ee) + X[15] + 0x7a6d76e9, 6) + aa; dd = RL(dd, 10); - aa = RL(aa + f2(bb,cc,dd) + X[ 0] + 0x7a6d76e9, 14) + ee; cc = RL(cc, 10); - ee = RL(ee + f2(aa,bb,cc) + X[ 5] + 0x7a6d76e9, 6) + dd; bb = RL(bb, 10); - dd = RL(dd + f2(ee,aa,bb) + X[12] + 0x7a6d76e9, 9) + cc; aa = RL(aa, 10); - cc = RL(cc + f2(dd,ee,aa) + X[ 2] + 0x7a6d76e9, 12) + bb; ee = RL(ee, 10); - bb = RL(bb + f2(cc,dd,ee) + X[13] + 0x7a6d76e9, 9) + aa; dd = RL(dd, 10); - aa = RL(aa + f2(bb,cc,dd) + X[ 9] + 0x7a6d76e9, 12) + ee; cc = RL(cc, 10); - ee = RL(ee + f2(aa,bb,cc) + X[ 7] + 0x7a6d76e9, 5) + dd; bb = RL(bb, 10); - dd = RL(dd + f2(ee,aa,bb) + X[10] + 0x7a6d76e9, 15) + cc; aa = RL(aa, 10); - cc = RL(cc + f2(dd,ee,aa) + X[14] + 0x7a6d76e9, 8) + bb; ee = RL(ee, 10); - - // - // Rounds 64-79 - // - // left - b = RL(b + f5(c,d,e) + X[ 4] + 0xa953fd4e, 9) + a; d = RL(d, 10); - a = RL(a + f5(b,c,d) + X[ 0] + 0xa953fd4e, 15) + e; c = RL(c, 10); - e = RL(e + f5(a,b,c) + X[ 5] + 0xa953fd4e, 5) + d; b = RL(b, 10); - d = RL(d + f5(e,a,b) + X[ 9] + 0xa953fd4e, 11) + c; a = RL(a, 10); - c = RL(c + f5(d,e,a) + X[ 7] + 0xa953fd4e, 6) + b; e = RL(e, 10); - b = RL(b + f5(c,d,e) + X[12] + 0xa953fd4e, 8) + a; d = RL(d, 10); - a = RL(a + f5(b,c,d) + X[ 2] + 0xa953fd4e, 13) + e; c = RL(c, 10); - e = RL(e + f5(a,b,c) + X[10] + 0xa953fd4e, 12) + d; b = RL(b, 10); - d = RL(d + f5(e,a,b) + X[14] + 0xa953fd4e, 5) + c; a = RL(a, 10); - c = RL(c + f5(d,e,a) + X[ 1] + 0xa953fd4e, 12) + b; e = RL(e, 10); - b = RL(b + f5(c,d,e) + X[ 3] + 0xa953fd4e, 13) + a; d = RL(d, 10); - a = RL(a + f5(b,c,d) + X[ 8] + 0xa953fd4e, 14) + e; c = RL(c, 10); - e = RL(e + f5(a,b,c) + X[11] + 0xa953fd4e, 11) + d; b = RL(b, 10); - d = RL(d + f5(e,a,b) + X[ 6] + 0xa953fd4e, 8) + c; a = RL(a, 10); - c = RL(c + f5(d,e,a) + X[15] + 0xa953fd4e, 5) + b; e = RL(e, 10); - b = RL(b + f5(c,d,e) + X[13] + 0xa953fd4e, 6) + a; d = RL(d, 10); - - // right - bb = RL(bb + f1(cc,dd,ee) + X[12], 8) + aa; dd = RL(dd, 10); - aa = RL(aa + f1(bb,cc,dd) + X[15], 5) + ee; cc = RL(cc, 10); - ee = RL(ee + f1(aa,bb,cc) + X[10], 12) + dd; bb = RL(bb, 10); - dd = RL(dd + f1(ee,aa,bb) + X[ 4], 9) + cc; aa = RL(aa, 10); - cc = RL(cc + f1(dd,ee,aa) + X[ 1], 12) + bb; ee = RL(ee, 10); - bb = RL(bb + f1(cc,dd,ee) + X[ 5], 5) + aa; dd = RL(dd, 10); - aa = RL(aa + f1(bb,cc,dd) + X[ 8], 14) + ee; cc = RL(cc, 10); - ee = RL(ee + f1(aa,bb,cc) + X[ 7], 6) + dd; bb = RL(bb, 10); - dd = RL(dd + f1(ee,aa,bb) + X[ 6], 8) + cc; aa = RL(aa, 10); - cc = RL(cc + f1(dd,ee,aa) + X[ 2], 13) + bb; ee = RL(ee, 10); - bb = RL(bb + f1(cc,dd,ee) + X[13], 6) + aa; dd = RL(dd, 10); - aa = RL(aa + f1(bb,cc,dd) + X[14], 5) + ee; cc = RL(cc, 10); - ee = RL(ee + f1(aa,bb,cc) + X[ 0], 15) + dd; bb = RL(bb, 10); - dd = RL(dd + f1(ee,aa,bb) + X[ 3], 13) + cc; aa = RL(aa, 10); - cc = RL(cc + f1(dd,ee,aa) + X[ 9], 11) + bb; ee = RL(ee, 10); - bb = RL(bb + f1(cc,dd,ee) + X[11], 11) + aa; dd = RL(dd, 10); - - dd += c + H1; - H1 = H2 + d + ee; - H2 = H3 + e + aa; - H3 = H4 + a + bb; - H4 = H0 + b + cc; - H0 = dd; - - // - // reset the offset and clean out the word buffer. - // - xOff = 0; - for (int i = 0; i != X.length; i++) - { - X[i] = 0; - } - } - - public Memoable copy() - { - return new RIPEMD160Digest(this); - } - - public void reset(Memoable other) - { - RIPEMD160Digest d = (RIPEMD160Digest)other; - - copyIn(d); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/CommitmentNotFoundException.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/CommitmentNotFoundException.java deleted file mode 100644 index 47af42bf2..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/CommitmentNotFoundException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions; - -public class CommitmentNotFoundException extends Exception { - public CommitmentNotFoundException(String message) { - super(message); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/DeserializationException.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/DeserializationException.java deleted file mode 100644 index 2b5d46265..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/DeserializationException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions; - -public class DeserializationException extends Exception { - public DeserializationException(String message) { - super(message); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/ExceededSizeException.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/ExceededSizeException.java deleted file mode 100644 index 7c2269a45..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/ExceededSizeException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions; - -public class ExceededSizeException extends Exception { - public ExceededSizeException(String message) { - super(message); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/UrlException.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/UrlException.java deleted file mode 100644 index d5a195505..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/UrlException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions; - -public class UrlException extends Exception { - public UrlException(String message) { - super(message); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/VerificationException.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/VerificationException.java deleted file mode 100644 index 39e24656a..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/exceptions/VerificationException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions; - -public class VerificationException extends Exception { - public VerificationException(String message) { - super(message); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Request.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Request.java deleted file mode 100644 index c2dd66c76..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Request.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.http; - -import android.util.Log; - -import java.io.DataOutputStream; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Callable; -import java.util.zip.GZIPInputStream; - -/** - * For making an HTTP request. - */ -public class Request implements Callable { - private URL url; - private byte[] data; - private Map headers; - private BlockingQueue queue; - - public Request(URL url) { - this.url = url; - } - - public void setData(byte[] data) { - this.data = data; - } - - public void setHeaders(Map headers) { - this.headers = headers; - } - - public void setQueue(BlockingQueue queue) { - this.queue = queue; - } - - @Override - public Response call() throws Exception { - Response response = new Response(); - - try { - HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); - httpURLConnection.setReadTimeout(10000); - httpURLConnection.setConnectTimeout(10000); - httpURLConnection.setRequestProperty("User-Agent", "OpenTimestamps Java"); - httpURLConnection.setRequestProperty("Accept", "application/json"); - httpURLConnection.setRequestProperty("Accept-Encoding", "gzip"); - - if (headers != null) { - for (Map.Entry entry : headers.entrySet()) { - httpURLConnection.setRequestProperty(entry.getKey(), entry.getValue()); - } - } - - if (data != null) { - httpURLConnection.setDoOutput(true); - httpURLConnection.setRequestMethod("POST"); - httpURLConnection.setRequestProperty("Content-Length", "" + Integer.toString(this.data.length)); - DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream()); - wr.write(this.data, 0, this.data.length); - wr.flush(); - wr.close(); - } else { - httpURLConnection.setRequestMethod("GET"); - } - - httpURLConnection.connect(); - - int responseCode = httpURLConnection.getResponseCode(); - - Log.i("OpenTimestamp", responseCode + " responseCode "); - - response.setStatus(responseCode); - response.setFromUrl(url.toString()); - InputStream is = httpURLConnection.getInputStream(); - if ("gzip".equals(httpURLConnection.getContentEncoding())) { - is = new GZIPInputStream(is); - } - response.setStream(is); - } catch (Exception e) { - Log.w("OpenTimestamp", url.toString() + " exception " + e); - } finally { - if (queue != null) { - queue.offer(response); - } - } - - return response; - } -} \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Response.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Response.java deleted file mode 100644 index d03a08c03..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/http/Response.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.http; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.json.JsonMapper; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; - -/** - * Holds the response from an HTTP request. - */ -public class Response { - private InputStream stream; - private String fromUrl; - private Integer status; - - public Response() { - } - - public Response(InputStream stream) { - this.stream = stream; - } - - public void setStream(InputStream stream) { - this.stream = stream; - } - - public Integer getStatus() { - return status; - } - - public void setStatus(Integer status) { - this.status = status; - } - - public boolean isOk() { - return getStatus() != null && 200 == getStatus(); - } - - public String getFromUrl() { - return fromUrl; - } - - public void setFromUrl(String fromUrl) { - this.fromUrl = fromUrl; - } - - public InputStream getStream() { - return this.stream; - } - - public String getString() throws IOException { - return new String(getBytes(), StandardCharsets.UTF_8); - } - - public byte[] getBytes() throws IOException { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - int nRead; - byte[] data = new byte[16384]; - - while ((nRead = this.stream.read(data, 0, data.length)) != -1) { - buffer.write(data, 0, nRead); - } - - buffer.flush(); - - return buffer.toByteArray(); - } - - public JsonNode getJson() throws IOException { - String jsonString = getString(); - JsonMapper builder = JsonMapper.builder().build(); - return builder.readTree(jsonString); - } -} \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/Op.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/Op.java deleted file mode 100644 index eccb53ec6..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/Op.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.op; - -import android.util.Log; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamSerializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException; - -/** - * Operations are the edges in the timestamp tree, with each operation taking a message and zero or more arguments to produce a result. - */ -public abstract class Op implements Comparable { - - /** - * Maximum length of an com.vitorpamplona.quartz.ots.op.Op result - *

- * For a verifier, this limit is what limits the maximum amount of memory you - * need at any one time to verify a particular timestamp path; while verifying - * a particular commitment operation path previously calculated results can be - * discarded. - *

- * Of course, if everything was a merkle tree you never need to append/prepend - * anything near 4KiB of data; 64 bytes would be plenty even with SHA512. The - * main need for this is compatibility with existing systems like Bitcoin - * timestamps and Certificate Transparency servers. While the pathological - * limits required by both are quite large - 1MB and 16MiB respectively - 4KiB - * is perfectly adequate in both cases for more reasonable usage. - *

- * @see Op subclasses should set this limit even lower if doing so is appropriate - * for them. - */ - public static int _MAX_RESULT_LENGTH = 4096; - - /** - * Maximum length of the message an com.vitorpamplona.quartz.ots.op.Op can be applied too. - *

- * Similar to the result length limit, this limit gives implementations a sane - * constraint to work with; the maximum result-length limit implicitly - * constrains maximum message length anyway. - *

- * com.vitorpamplona.quartz.ots.op.Op subclasses should set this limit even lower if doing so is appropriate - * for them. - */ - public static int _MAX_MSG_LENGTH = 4096; - - public static byte _TAG = (byte) 0x00; - - public String _TAG_NAME() { - return ""; - } - - public byte _TAG() { - return Op._TAG; - } - - /** - * Deserialize operation from a buffer. - * - * @param ctx The stream deserialization context. - * @return The subclass Operation. - */ - public static Op deserialize(StreamDeserializationContext ctx) throws DeserializationException { - byte tag = ctx.readBytes(1)[0]; - - return Op.deserializeFromTag(ctx, tag); - } - - /** - * Deserialize operation from a buffer. - * - * @param ctx The stream deserialization context. - * @param tag The tag of the operation. - * @return The subclass Operation. - */ - public static Op deserializeFromTag(StreamDeserializationContext ctx, byte tag) - throws DeserializationException { - if (tag == OpAppend._TAG) { - return OpAppend.deserializeFromTag(ctx, tag); - } else if (tag == OpPrepend._TAG) { - return OpPrepend.deserializeFromTag(ctx, tag); - } else if (tag == OpSHA1._TAG) { - return OpSHA1.deserializeFromTag(ctx, tag); - } else if (tag == OpSHA256._TAG) { - return OpSHA256.deserializeFromTag(ctx, tag); - } else if (tag == OpRIPEMD160._TAG) { - return OpRIPEMD160.deserializeFromTag(ctx, tag); - } else if (tag == OpKECCAK256._TAG) { - return OpKECCAK256.deserializeFromTag(ctx, tag); - } else { - Log.e("OpenTimestamp", "Unknown operation tag: " + tag + " 0x" + String.format("%02x", tag)); - return null; // TODO: Is this OK? Won't it blow up later? Better to throw? - } - } - - /** - * Serialize operation. - * - * @param ctx The stream serialization context. - */ - public void serialize(StreamSerializationContext ctx) { - if (this._TAG() == 0x00) { - Log.e("OpenTimestamp", "No valid serialized Op"); - // TODO: Is it OK to just log and carry on? Won't it blow up later? Better to throw? - } - - ctx.writeByte(this._TAG()); - } - - /** - * Apply the operation to a message. - * Raises MsgValueError if the message value is invalid, such as it being - * too long, or it causing the result to be too long. - * - * @param msg The message. - * @return the msg after the operation has been applied - */ - public byte[] call(byte[] msg) { - if (msg.length > _MAX_MSG_LENGTH) { - Log.e("OpenTimestamp", "Error : Message too long;"); - return new byte[]{}; // TODO: Is this OK? Won't it blow up later? Better to throw? - } - - byte[] r = this.call(msg); - - if (r.length > _MAX_RESULT_LENGTH) { - Log.e("OpenTimestamp", "Error : Result too long;"); - // TODO: Is it OK to just log and carry on? Won't it blow up later? Better to throw? - } - - return r; - } - - @Override - public int compareTo(Op o) { - return this._TAG() - o._TAG(); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpAppend.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpAppend.java deleted file mode 100644 index e1631278a..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpAppend.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.op; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException; - -import java.util.Arrays; - -/** - * Append a suffix to a message. - * - * @see OpBinary - */ -public class OpAppend extends OpBinary { - byte[] arg; - - public static byte _TAG = (byte) 0xf0; - - @Override - public byte _TAG() { - return OpAppend._TAG; - } - - @Override - public String _TAG_NAME() { - return "append"; - } - - public OpAppend() { - super(); - this.arg = new byte[]{}; - } - - public OpAppend(byte[] arg_) { - super(arg_); - this.arg = arg_; - } - - @Override - public byte[] call(byte[] msg) { - return Utils.arraysConcat(msg, this.arg); - } - - public static Op deserializeFromTag(StreamDeserializationContext ctx, byte tag) - throws DeserializationException { - return OpBinary.deserializeFromTag(ctx, tag); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof OpAppend)) { - return false; - } - - return Arrays.equals(this.arg, ((OpAppend) obj).arg); - } - - @Override - public int hashCode() { - return _TAG ^ Arrays.hashCode(this.arg); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpBinary.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpBinary.java deleted file mode 100644 index 5a16b9732..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpBinary.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.op; - -import android.util.Log; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamSerializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException; -import com.vitorpamplona.quartz.utils.Hex; - -import java.util.Arrays; -import java.util.Locale; - -/** - * Operations that act on a message and a single argument. - * - * @see OpUnary - */ -public abstract class OpBinary extends Op implements Comparable { - - public byte[] arg; - - @Override - public String _TAG_NAME() { - return ""; - } - - public OpBinary() { - super(); - this.arg = new byte[]{}; - } - - public OpBinary(byte[] arg_) { - super(); - this.arg = arg_; - } - - public static Op deserializeFromTag(StreamDeserializationContext ctx, byte tag) - throws DeserializationException { - byte[] arg = ctx.readVarbytes(_MAX_RESULT_LENGTH, 1); - - if (tag == OpAppend._TAG) { - return new OpAppend(arg); - } else if (tag == OpPrepend._TAG) { - return new OpPrepend(arg); - } else { - Log.e("OpenTimestamp", "Unknown operation tag: " + tag + " 0x" + String.format("%02x", tag)); - return null; // TODO: Is this OK? Won't it blow up later? Better to throw? - } - } - - @Override - public void serialize(StreamSerializationContext ctx) { - super.serialize(ctx); - ctx.writeVarbytes(this.arg); - } - - @Override - public String toString() { - return this._TAG_NAME() + ' ' + Hex.encode(this.arg).toLowerCase(Locale.ROOT); - } - - @Override - public int compareTo(Op o) { - if (o instanceof OpBinary && this._TAG() == o._TAG()) { - return Utils.compare(this.arg, ((OpBinary) o).arg); - } - - return this._TAG() - o._TAG(); - } - - @Override - public int hashCode() { - return _TAG ^ Arrays.hashCode(this.arg); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpCrypto.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpCrypto.java deleted file mode 100644 index 4ba85d345..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpCrypto.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.op; - -import android.util.Log; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -/** - * Cryptographic transformations. - * These transformations have the unique property that for any length message, - * the size of the result they return is fixed. Additionally, they're the only - * type of operation that can be applied directly to a stream. - * - * @see OpUnary - */ -public class OpCrypto extends OpUnary { - - public String _TAG_NAME = ""; - - public String _HASHLIB_NAME() { - return ""; - } - - public int _DIGEST_LENGTH() { - return 0; - } - - OpCrypto() { - super(); - } - - public static Op deserializeFromTag(StreamDeserializationContext ctx, byte tag) { - return OpUnary.deserializeFromTag(ctx, tag); - } - - @Override - public byte[] call(byte[] msg) { - // For Sha1 & Sha256 use java.security.MessageDigest library - try { - MessageDigest digest = MessageDigest.getInstance(this._HASHLIB_NAME()); - byte[] hash = digest.digest(msg); - - return hash; - } catch (NoSuchAlgorithmException e) { - Log.e("OpenTimestamp", "NoSuchAlgorithmException"); - e.printStackTrace(); - - return new byte[]{}; // TODO: Is this OK? Won't it blow up later? Better to throw? - } - } - - public byte[] hashFd(StreamDeserializationContext ctx) throws NoSuchAlgorithmException { - MessageDigest digest = MessageDigest.getInstance(this._HASHLIB_NAME()); - byte[] chunk = ctx.read(1048576); - - while (chunk != null && chunk.length > 0) { - digest.update(chunk); - chunk = ctx.read(1048576); - } - - byte[] hash = digest.digest(); - - return hash; - } - - public byte[] hashFd(File file) throws IOException, NoSuchAlgorithmException { - return hashFd(new FileInputStream(file)); - } - - public byte[] hashFd(byte[] bytes) throws IOException, NoSuchAlgorithmException { - StreamDeserializationContext ctx = new StreamDeserializationContext(bytes); - - return hashFd(ctx); - } - - public byte[] hashFd(InputStream inputStream) throws IOException, NoSuchAlgorithmException { - MessageDigest digest = MessageDigest.getInstance(this._HASHLIB_NAME()); - byte[] chunk = new byte[1048576]; - int count = inputStream.read(chunk, 0, 1048576); - - while (count >= 0) { - digest.update(chunk, 0, count); - count = inputStream.read(chunk, 0, 1048576); - } - - inputStream.close(); - byte[] hash = digest.digest(); - - return hash; - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpKECCAK256.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpKECCAK256.java deleted file mode 100644 index 47e2185d4..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpKECCAK256.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.op; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.crypto.KeccakDigest; - -/** - * Cryptographic Keccak256 operation. - * Cryptographic operation tag numbers taken from RFC4880, although it's not - * guaranteed that they'll continue to match that RFC in the future. - * - * @see OpCrypto - */ -public class OpKECCAK256 extends OpCrypto { - private KeccakDigest digest = new KeccakDigest(256); - - public static byte _TAG = (byte) 103; - - @Override - public byte _TAG() { - return OpKECCAK256._TAG; - } - - @Override - public String _TAG_NAME() { - return "keccak256"; - } - - @Override - public String _HASHLIB_NAME() { - return "keccak256"; - } - - @Override - public int _DIGEST_LENGTH() { - return digest.getDigestSize(); - } - - public OpKECCAK256() { - super(); - } - - @Override - public byte[] call(byte[] msg) { - digest.update(msg, 0, msg.length); - byte[] hash = new byte[digest.getDigestSize()]; - digest.doFinal(hash, 0); - - return hash; - } - - public static Op deserializeFromTag(StreamDeserializationContext ctx, byte tag) { - return OpCrypto.deserializeFromTag(ctx, tag); - } - - @Override - public boolean equals(Object obj) { - return (obj instanceof OpKECCAK256); - } -} \ No newline at end of file diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpPrepend.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpPrepend.java deleted file mode 100644 index 510749f89..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpPrepend.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.op; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.Utils; -import com.vitorpamplona.quartz.nip03Timestamp.ots.exceptions.DeserializationException; - -import java.util.Arrays; - -/** - * Prepend a prefix to a message. - * - * @see OpBinary - */ -public class OpPrepend extends OpBinary { - - byte[] arg; - - public static byte _TAG = (byte) 0xf1; - - @Override - public byte _TAG() { - return OpPrepend._TAG; - } - - @Override - public String _TAG_NAME() { - return "prepend"; - } - - public OpPrepend() { - super(); - this.arg = new byte[]{}; - } - - public OpPrepend(byte[] arg_) { - super(arg_); - this.arg = arg_; - } - - @Override - public byte[] call(byte[] msg) { - return Utils.arraysConcat(this.arg, msg); - } - - public static Op deserializeFromTag(StreamDeserializationContext ctx, byte tag) - throws DeserializationException { - return OpBinary.deserializeFromTag(ctx, tag); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof OpPrepend)) { - return false; - } - - return Arrays.equals(this.arg, ((OpPrepend) obj).arg); - } - - @Override - public int hashCode() { - return _TAG ^ Arrays.hashCode(this.arg); - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpRIPEMD160.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpRIPEMD160.java deleted file mode 100644 index 4ef69398c..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpRIPEMD160.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.op; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; -import com.vitorpamplona.quartz.nip03Timestamp.ots.crypto.RIPEMD160Digest; - -/** - * Cryptographic RIPEMD160 operation. - * Cryptographic operation tag numbers taken from RFC4880, although it's not - * guaranteed that they'll continue to match that RFC in the future. - * - * @see OpCrypto - */ -public class OpRIPEMD160 extends OpCrypto { - - public static byte _TAG = 0x03; - - @Override - public byte _TAG() { - return OpRIPEMD160._TAG; - } - - @Override - public String _TAG_NAME() { - return "ripemd160"; - } - - @Override - public String _HASHLIB_NAME() { - return "ripemd160"; - } - - @Override - public int _DIGEST_LENGTH() { - return 20; - } - - public OpRIPEMD160() { - super(); - } - - @Override - public byte[] call(byte[] msg) { - RIPEMD160Digest digest = new RIPEMD160Digest(); - digest.update(msg, 0, msg.length); - byte[] hash = new byte[digest.getDigestSize()]; - digest.doFinal(hash, 0); - - return hash; - } - - public static Op deserializeFromTag(StreamDeserializationContext ctx, byte tag) { - return OpCrypto.deserializeFromTag(ctx, tag); - } - - @Override - public boolean equals(Object obj) { - return (obj instanceof OpRIPEMD160); - } - - @Override - public int hashCode() { - return _TAG; - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA1.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA1.java deleted file mode 100644 index 055705677..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA1.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.op; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; - -/** - * Cryptographic SHA1 operation. - * Cryptographic operation tag numbers taken from RFC4880, although it's not - * guaranteed that they'll continue to match that RFC in the future. - * Remember that for timestamping, hash algorithms with collision attacks - * *are* secure! We've still proven that both messages existed prior to some - * point in time - the fact that they both have the same hash digest doesn't - * change that. - * Heck, even md5 is still secure enough for timestamping... but that's - * pushing our luck... - * - * @see OpCrypto - */ -public class OpSHA1 extends OpCrypto { - - - public static byte _TAG = 0x02; - - @Override - public byte _TAG() { - return OpSHA1._TAG; - } - - @Override - public String _TAG_NAME() { - return "sha1"; - } - - @Override - public String _HASHLIB_NAME() { - return "SHA-1"; - } - - @Override - public int _DIGEST_LENGTH() { - return 20; - } - - public OpSHA1() { - super(); - } - - @Override - public byte[] call(byte[] msg) { - return super.call(msg); - } - - public static Op deserializeFromTag(StreamDeserializationContext ctx, byte tag) { - return OpCrypto.deserializeFromTag(ctx, tag); - } - - @Override - public boolean equals(Object obj) { - return (obj instanceof OpSHA1); - } - - @Override - public int hashCode() { - return _TAG; - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA256.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA256.java deleted file mode 100644 index c5772c2e3..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpSHA256.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.op; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; - -/** - * Cryptographic SHA256 operation. - * Cryptographic operation tag numbers taken from RFC4880, although it's not - * guaranteed that they'll continue to match that RFC in the future. - * - * @see OpCrypto - */ -public class OpSHA256 extends OpCrypto { - - - public static byte _TAG = 0x08; - - @Override - public byte _TAG() { - return OpSHA256._TAG; - } - - @Override - public String _TAG_NAME() { - return "sha256"; - } - - @Override - public String _HASHLIB_NAME() { - return "SHA-256"; - } - - @Override - public int _DIGEST_LENGTH() { - return 32; - } - - public OpSHA256() { - super(); - } - - @Override - public byte[] call(byte[] msg) { - return super.call(msg); - } - - public static Op deserializeFromTag(StreamDeserializationContext ctx, byte tag) { - return OpCrypto.deserializeFromTag(ctx, tag); - } - - @Override - public boolean equals(Object obj) { - return (obj instanceof OpSHA256); - } - - @Override - public int hashCode() { - return _TAG; - } -} diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpUnary.java b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpUnary.java deleted file mode 100644 index 458a75b31..000000000 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/ots/op/OpUnary.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.vitorpamplona.quartz.nip03Timestamp.ots.op; - -import android.util.Log; - -import com.vitorpamplona.quartz.nip03Timestamp.ots.StreamDeserializationContext; - -/** - * Operations that act on a single message. - * - * @see Op - */ -public abstract class OpUnary extends Op { - - @Override - public String _TAG_NAME() { - return ""; - } - - public OpUnary() { - super(); - } - - public static Op deserializeFromTag(StreamDeserializationContext ctx, byte tag) { - if (tag == OpSHA1._TAG) { - return new OpSHA1(); - } else if (tag == OpSHA256._TAG) { - return new OpSHA256(); - } else if (tag == OpRIPEMD160._TAG) { - return new OpRIPEMD160(); - } else if (tag == OpKECCAK256._TAG) { - return new OpKECCAK256(); - } else { - Log.e("OpenTimestamp", "Unknown operation tag: " + tag); - - return null; // TODO: Is this OK? Won't it blow up later? Better to throw? - } - } - - @Override - public String toString() { - return this._TAG_NAME(); - } -} diff --git a/quartz/src/test/java/android/util/Log.java b/quartz/src/test/java/android/util/Log.java deleted file mode 100644 index af85d0b47..000000000 --- a/quartz/src/test/java/android/util/Log.java +++ /dev/null @@ -1,35 +0,0 @@ -package android.util; - -public class Log { - public static int d(String tag, String msg) { - System.out.println("DEBUG: " + tag + ": " + msg); - return 0; - } - - public static int i(String tag, String msg) { - System.out.println("INFO: " + tag + ": " + msg); - return 0; - } - - public static int w(String tag, String msg) { - System.out.println("WARN: " + tag + ": " + msg); - return 0; - } - - public static int w(String tag, String msg, Throwable e) { - System.out.println("WARN: " + tag + ": " + msg); - e.printStackTrace(); - return 0; - } - - public static int e(String tag, String msg) { - System.out.println("ERROR: " + tag + ": " + msg); - return 0; - } - - public static int e(String tag, String msg, Throwable e) { - System.out.println("ERROR: " + tag + ": " + msg); - e.printStackTrace(); - return 0; - } -} \ No newline at end of file