tcheeric / nostr-java Goto Github PK
View Code? Open in Web Editor NEWA nostr library, written in java, for generating, signing and publishing events.
License: MIT License
A nostr library, written in java, for generating, signing and publishing events.
License: MIT License
Is your feature request related to a problem? Please describe.
Compatible with repost kind such as 'TEXT_NOTE' and 'REACTION’
Describe the solution you'd like
Add repost kind to Kind.java
Additional context
The information about repost kind (kind:6) can be found at https://github.com/nostr-protocol/nips#event-kinds
Create the pubkey tags based on the list of public keys.
To Reproduce
Steps to reproduce the behavior:
execute the following test.
package nostr.test.event;
import nostr.event.impl.GenericMessage;
import nostr.event.json.codec.BaseMessageDecoder;
import nostr.util.NostrException;
import org.junit.jupiter.api.Test;
public class DecodeTest {
@Test
public void decodeTest() throws NostrException {
String json = "[" +
"\"EVENT\"," +
"\"temp20230627\"," +
"{" +
"\"id\":\"28f2fc030e335d061f0b9d03ce0e2c7d1253e6fadb15d89bd47379a96b2c861a\"," +
"\"kind\":1," +
"\"pubkey\":\"2bed79f81439ff794cf5ac5f7bff9121e257f399829e472c7a14d3e86fe76984\"," +
"\"created_at\":1687765220," +
"\"content\":\"手順書が間違ってたら作業者は無理だな\"," +
"\"tags\":[" +
"[\"e\",\"494001ac0c8af2a10f60f23538e5b35d3cdacb8e1cc956fe7a16dfa5cbfc4346\",\"\",\"root\"]," +
"[\"p\",\"2bed79f81439ff794cf5ac5f7bff9121e257f399829e472c7a14d3e86fe76984\"]" +
"]," +
"\"sig\":\"86f25c161fec51b9e441bdb2c09095d5f8b92fdce66cb80d9ef09fad6ce53eaa14c5e16787c42f5404905536e43ebec0e463aee819378a4acbe412c533e60546\"" +
"}]";
BaseMessageDecoder decoder = new BaseMessageDecoder(json);
GenericMessage message = decoder.decode();
}
}
Expected behavior
It is expected to generate a 'GenericMessage'
The actual result.
The following exception occurred.
java.lang.IllegalArgumentException: No enum constant nostr.event.Marker.root (through reference chain: nostr.event.impl.GenericEvent["tags"]->java.util.ArrayList[0])
at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4449)
at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:4390)
at nostr.event.json.codec.BaseMessageDecoder.decode(BaseMessageDecoder.java:79)
at nostr.test.event.DecodeTest.decodeTest(DecodeTest.java:30)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: No enum constant nostr.event.Marker.root (through reference chain: nostr.event.impl.GenericEvent["tags"]->java.util.ArrayList[0])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:402)
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:373)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:375)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:314)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4444)
... 73 more
Caused by: java.lang.IllegalArgumentException: No enum constant nostr.event.Marker.root
at java.base/java.lang.Enum.valueOf(Enum.java:273)
at nostr.event.Marker.valueOf(Marker.java:8)
at nostr.event.json.deserializer.TagDeserializer.deserialize(TagDeserializer.java:86)
at nostr.event.json.deserializer.TagDeserializer.deserialize(TagDeserializer.java:19)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:359)
... 79 more
Additional context
The cause is that the Enum constants are in uppercase, while the JSON markers are in lowercase.
It's necessary to improve the marshal to json for using Jackson. It'll make the code cleaner and maintainable.
Something like that Jackson – Marshal and Unmarshal.
Describe the bug
The RelayInformationDocument class inside the Relay class is using member names that do not match the JSON.
To Reproduce
Steps to reproduce the behavior:
Additional context
In the JSON, the correct names to be used are "supported_nips", "supported_nip_extensions", and "payments_url" instead of "supportedNips", "supportedNipExtensions", and "paymentsUrl".
Currently, you can only sign events with the identity configured in the profile.properties.
Make the necessary changes in nostr-api to provide a different identity for signing events
Filters kinds are encoded as array of String, instead of array of integers.
I believe this is because of
@JsonValue String Kind.toString()
This causes the following error:
testCreateTextNoteEvent Tests run: 7, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.613 s <<< FAILURE! - in nostr.test.event.EventTest testUnmarshallEvent Time elapsed: 0.108 s <<< ERROR! java.lang.ClassCastException: class nostr.types.values.impl.StringValue cannot be cast to class nostr.types.values.impl.NumberValue (nostr.types.values.impl.StringValue and nostr.types.values.impl.NumberValue are in unnamed module of loader 'app') at nostr.test.event.EventTest.testUnmarshallEvent(EventTest.java:209)
This requires changes in nostr.id.IdentityHelper.
(May need refactoring)
Describe the bug
In TagDeserializer.java, when the code is "nonce", both nodeNonce and nodeDifficulty are set to node.get(1).
Expected behavior
Most likely, nodeDifficulty should reference node.get(2).
Additional context
Does nonce fit within the range of an Integer data type? Is it possible for larger numbers to be included?
The word 'publickKey' exists in Identity.java and profile.properties.
Isn't the publicKey correct?
Is your feature request related to a problem? Please describe.
Compatible with mention markers such as 'root' and 'replay’
Describe the solution you'd like
Add mention marker to Marker.java
Additional context
The information about mention markers can be found at https://github.com/nostr-protocol/nips/blob/master/10.md.
Apr 06, 2023 2:43:59 AM nostr.id.Client updateRelayInformation
SEVERE: null
java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because the return value of "java.net.URI.getScheme()" is null
at nostr.ws.Connection.connect(Connection.java:114)
at nostr.ws.Connection.(Connection.java:68)
at nostr.id.Client.updateRelayInformation(Client.java:142)
at nostr.id.Client.openRelay(Client.java:117)
at nostr.id.Client.lambda$init$4(Client.java:126)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Describe the bug
Even if the message is received successfully, parsing from the message to List fails in ResponseHandlerImpl.
Expected behavior
The message to be parsed into a List.
Additional context
The received message is a string surrounded by square brackets [], and it is not in JSON format, so it cannot be converted to String[] using objectMapper.readValue(message, String[].class).
Branch: feature/NIP42_Issue_80
auth-required:
warning messageDescribe
When connected to certain relays,
there is an item in RelayInformation that is not specified in NIP-11 called "id," causing a failure in converting it to Relay.RelayInformationDocument.
Additional context
The relay that is using nostr-rs-relay returns an item called "id" in RelayInformation.
I couldn't determine whether nostr-java or nostr-rs-relay is at fault.
The error occurs occasionally when running the nostr.examples.NostrExamples
main class in the java-nostr-examples maven module. The issue is reproducible with the code in the feature_bug_fixes
branch
Jun 15, 2023 10:04:03 PM nostr.id.Client lambda$send$2
WARNING: null
java.util.concurrent.ExecutionException: java.lang.RuntimeException
at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
at nostr.id.Client.lambda$send$2(Client.java:106)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178)
at java.base/java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1707)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:290)
at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:754)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:686)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:159)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateParallel(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at nostr.id.Client.send(Client.java:112)
at nostr.examples.NostrExamples.sendEncryptedDirectMessage(NostrExamples.java:267)
at nostr.examples.NostrExamples.lambda$main$1(NostrExamples.java:107)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.RuntimeException
at nostr.ws.Connection.serverURI(Connection.java:102)
at nostr.id.Client.openRelay(Client.java:158)
at nostr.id.Client.lambda$init$5(Client.java:174)
... 4 more
Jun 15, 2023 10:04:03 PM nostr.ws.response.handler.provider.ResponseHandlerImpl <init>
WARNING: No custom command handler provided. Using default command handler
Jun 15, 2023 10:04:03 PM nostr.id.Client lambda$send$2
WARNING: null
java.util.concurrent.ExecutionException: java.lang.RuntimeException
at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
at nostr.id.Client.lambda$send$2(Client.java:106)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178)
at java.base/java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1707)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:290)
at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:754)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:686)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:159)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateParallel(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at nostr.id.Client.send(Client.java:112)
at nostr.examples.NostrExamples.createChannel(NostrExamples.java:486)
at nostr.examples.NostrExamples.sendChannelMessage(NostrExamples.java:524)
at nostr.examples.NostrExamples.lambda$main$12(NostrExamples.java:195)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.RuntimeException
at nostr.ws.Connection.serverURI(Connection.java:102)
at nostr.id.Client.openRelay(Client.java:158)
at nostr.id.Client.lambda$init$5(Client.java:174)
... 4 more
NIP-03 has changed since it was last implemented. Update the code to take into account the changes made to the spec.
Describe
Regarding the profile name, a pattern match is being performed with "\w[\w-]+\w" in validate() in MetadataEvent.java
Is this restriction unnecessary?
Additional context
In"NIP-01," it is only specified as "name: " without any restrictions regarding patterns or character types.
What considerations do you have for receiving messages (such as replies to "REQ") in the "Client" class?
When I call the Client.send() from my client app, it doesn't send the message to the relay. It appears it never enters the forEach() section of the parallel stream defined in the method.
In my example below, I am trying to submit a REQ-message containing a filter to extract NIP-4 messages sent to a specific pubkey.
--- exec-maven-plugin:3.1.0:exec (default-cli) @ nostr-bot-client ---
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Apr 17, 2023 10:42:57 AM nostr.bot.job.NostrJob execute
INFO: Executing job: group1.NostrBotJob executing at 17/04/2023, 10:42,fired by: group1.NostrBotTrigger
Apr 17, 2023 10:42:57 AM nostr.bot.job.impl.AbstractPublisher lambda$publish$0
INFO: Filtering event since 1,681,724,455
Apr 17, 2023 10:42:57 AM nostr.bot.job.impl.AbstractPublisher lambda$publish$0
INFO: Filters: Filters(events=null, authors=null, kinds=BaseList(list=[4]), referencedEvents=null, referencePubKeys=BaseList(list=[f6a04a16b1fb3b4bf40838dacc7f8bd4d46b60d3c9e2a4915877f9a2eac8e323]), since=1681724455, until=null, limit=null, genericTagQueryList=null)
Apr 17, 2023 10:42:57 AM nostr.bot.job.impl.AbstractPublisher lambda$publish$0
INFO: Sending message ReqMessage(super=GenericMessage(command=REQ, attributes=[], nip=1), subscriptionId=nostr-bot, filters=Filters(events=null, authors=null, kinds=BaseList(list=[4]), referencedEvents=null, referencePubKeys=BaseList(list=[f6a04a16b1fb3b4bf40838dacc7f8bd4d46b60d3c9e2a4915877f9a2eac8e323]), since=1681724455, until=null, limit=null, genericTagQueryList=null))
Apr 17, 2023 10:42:57 AM nostr.bot.util.BotUtil storeLongToFile
INFO: Storing value 1,681,724,577 to file...
Apr 17, 2023 10:42:59 AM nostr.ws.handler.BaseHandler process
INFO: process
Sorry if this came up before (did a search and found nothing).
I am trying to create multiple filters, nothing too complex..
e.g. (KIND 1 from Pubkey A) or (KIND 30 from Pubkey B) in a single subscription.
Shouldn't the ReqMessage
have the ability to specify multiple Filters
objects?
In certain scenarios, locating the configuration file fails.
Fixed in branch. Will add unit tests and merge.
Nonce mining is slow on json object, on string is fast but on bytes is the fastest.
Have been trying to develop an nostr server, and looked at the event id mining.
Thus gave it a try as a unit test, and thought to share it as you may need equal like code;
@Test
public void testMining() throws Exception {
Duration maxMining = Duration.ofSeconds(360);
int maxDifficulty = (OctoTrust.KEY_LENGTH * 8) / 2; // is 128 thus 50% of bits are zero
NoStrIdentity nid = new NoStrIdentity(NoStrIdentityPrivateKey.ofRandom());
try (JsonReader reader = Json.createReader(new InputStreamReader(getClass().getResourceAsStream("note-text-simple.json")))) {
NoStrEvent event = new NoStrEvent(reader.readObject());
Assertions.assertTrue(NoStrEventSignature.verify(event));
int testOffsetDifficulty = 10; // +12 from note-text-simple.json
// use test public key and copy others
NoStrEventPayload payload = new NoStrEventPayload(nid.getPublicKey(), event.getPayload().getCreatedAt(), event.getPayload().getKind(), event.getPayload().getTags(), event.getPayload().getContent());
Optional<NoStrEventTag> nonceTagOpt = payload.findFirstByQName(NoStrImplEventTag.NONCE);
if (nonceTagOpt.isEmpty()) {
return; // no mining requested
}
// replace X NoStrEventTag impl or NoStrEventTagCustom or NoStrTagNonce with local tag for setter access
NoStrTagNonce nonceTag = new NoStrTagNonce(Integer.parseInt(nonceTagOpt.get().getMetaArgument(NoStrImplTagNonce.DIFFICULTY).get()) + testOffsetDifficulty);
int nonceTagIdx = payload.getTags().indexOf(nonceTagOpt.get());
payload.getTags().set(nonceTagIdx, nonceTag);
int targetDifficulty = nonceTag.getDifficulty();
if (targetDifficulty > maxDifficulty) {
throw new IllegalArgumentException("Target difficulty can't be larger than " + maxDifficulty);
}
int mineCnt = 0;
byte[] eventId = null;
int leadingZeroBits = 0;
byte[] nowStr = Long.toString(payload.getCreatedAt().getEpochSecond()).getBytes(StandardCharsets.UTF_8);
byte[] payloadStr = NoStrEventSignature.generateEventIdJsonString(payload).getBytes(StandardCharsets.UTF_8);
int createdAtLength = nowStr.length;
int createdAtIdx = indexOf(payloadStr, nowStr, indexOf(payloadStr, new byte[]{'\"'}, 5));
int nonceProofIdx = indexOf(payloadStr, "\"nonce\"".getBytes(StandardCharsets.UTF_8), 0) + 9;// ["nonce","7539","12"]],
int nonceProofLength = Integer.toString(nonceTag.getBearerProof()).getBytes(StandardCharsets.UTF_8).length;
long createdAtTime = System.currentTimeMillis();
long maxMiningTime = createdAtTime + maxMining.toMillis();
MessageDigest sha256 = OctoTrustHash.sha256Algorithm();
while (leadingZeroBits < targetDifficulty) {
mineCnt++;
createdAtTime = System.currentTimeMillis();
if (createdAtTime > maxMiningTime) {
throw new IllegalStateException("Mining resource limit exceeded");
}
long createdAtTimeSecs = createdAtTime / 1000;
int createdAtTimeDigits = numDigits(createdAtTimeSecs);
if (createdAtLength != createdAtTimeDigits) {
createdAtLength = createdAtTimeDigits;
payloadStr = growBySplit(payloadStr, createdAtIdx);
}
writeDigits(createdAtTimeSecs, createdAtTimeDigits, payloadStr, createdAtIdx);
int nonceProofDigits = numDigits(mineCnt);
if (nonceProofLength != nonceProofDigits) {
nonceProofLength = nonceProofDigits;
payloadStr = growBySplit(payloadStr, nonceProofIdx);
}
writeDigits(mineCnt, nonceProofDigits, payloadStr, nonceProofIdx);
eventId = sha256.digest(payloadStr);
leadingZeroBits = 0;
for (int i = 0; i < eventId.length; i++) {
int step = eventId[i] & 0xFF; // force unsigned
if (step == 0) {
leadingZeroBits += 8;
continue;
}
leadingZeroBits += Integer.numberOfLeadingZeros(step) - 24;
break;
}
}
payload.setCreatedAt(Instant.ofEpochMilli(createdAtTime));
nonceTag.setBearerProof(mineCnt);
NoStrEvent eventMined = NoStrEventSignature.sign(payload, nid.getPrivateKey(), eventId);
System.out.println("idOrg=" + event.getId().getHex());
System.out.println("idHex=" + eventMined.getId().getHex());
System.out.println("idStr=" + NoStrEventSignature.generateEventIdJsonString(payload));
System.out.println("leadZero=" + leadingZeroBits);
System.out.println("mineCnt=" + mineCnt);
System.out.println("idStrHex=" + OctoBitFormat.HEX.fromBytes(NoStrEventSignature.generateEventIdJsonString(payload).getBytes(StandardCharsets.UTF_8)));
System.out.println("idStrArr=" + OctoBitFormat.HEX.fromBytes(payloadStr));
Assertions.assertTrue(NoStrEventSignature.verify(eventMined));
Assertions.assertEquals("" + mineCnt, eventMined.getPayload().findFirstByQName("nonce").get().getMetaArgument(0).get());
Assertions.assertEquals("" + targetDifficulty, eventMined.getPayload().findFirstByQName("nonce").get().getMetaArgument(1).get());
}
}
public byte[] growBySplit(byte[] src, int splitIdx) {
byte[] result = new byte[src.length + 1];
System.arraycopy(src, 0, result, 0, splitIdx);
System.arraycopy(src, splitIdx + 1, result, splitIdx + 2, src.length - splitIdx - 1);
return result;
}
public void writeDigits(long value, int digits, byte[] target, int off) {
int i = digits - 1;
while (value > 0) {
target[i+off] = (byte) ((value % 10) + '0');
value /= 10;
i--;
}
}
public int numDigits(long n) {
return (int) Math.log10(n) + 1;
}
public int indexOf(byte[] source, byte[] target, int fromIndex) {
return indexOf(source, 0, source.length, target, 0, target.length, fromIndex);
}
public int indexOf(byte[] source, int sourceOffset, int sourceCount, byte[] target, int targetOffset, int targetCount, int fromIndex) {
if (fromIndex >= sourceCount) {
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
if (targetCount == 0) {
return fromIndex;
}
byte first = target[targetOffset];
int max = sourceOffset + (sourceCount - targetCount);
for (int i = sourceOffset + fromIndex; i <= max; i++) {
if (source[i] != first) { // search first
while (++i <= max && source[i] != first) {
;
}
}
if (i <= max) { // search left over
int j = i + 1;
int end = j + targetCount - 1;
for (int k = targetOffset + 1; j < end && source[j] == target[k]; j++, k++) {
;
}
if (j == end) {
return i - sourceOffset;
}
}
}
return -1;
}
NIP-24 Sealed Gift-Wrapped Messages for Private DMs and Small Group Chats
Why isn't it generating privkeys and pubkeys? Well, it's necessary to implement this feature.
Hi there - this looks like a really useful collection of stuff for playing with Nostr in Javaland... so thank you for that!
Just having a problem building as the HEAD seems to be missing this shnorr dependency that I couldn't see on Github.
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>nostr-schnorr</artifactId>
<version>${project.version}</version>
</dependency>
cheers! :0)
Hi there,
This is a lovely set of libs - so thank you for that! I would like to use them in the relay project I am working on. I can fork it and pull updates periodically but it would be much nicer if I could just pull the binaries from maven central or another repo.
One simple option is https://jitpack.io
com.github
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
That's it.
What do you think about changing the structure of the project? Instead of have a multi-modules structure, we'd have just one module maven with many packages (to organize the code). It'll be easiest to integrate the code among the packages. Today we have a lot of problems with dependencies because maven can't have cyclic dependencies (you can read more about it here).
Describe the bug
The java.util.NoSuchElementException occurs in the constructor of ResponseHandlerImpl.
To Reproduce
Expected behavior
The exception does not occur.
Additional context
Is it correct to have the expression "filter(ch -> !ch.getClass().isAnnotationPresent(DefaultHandler.class))" inside the constructor of ResponseHandlerImpl? Shouldn't it be "filter(ch -> ch.getClass().isAnnotationPresent(DefaultHandler.class))" instead?
Is it a Netbeans configuration file? Why these files are versionated on git?
Can we delete them and add in .gitignore?
Client does not belong to nostr-java-id, I will create nostr-java-client and move it there.
Describe the bug
"Kind":0 Event failed and Failed to update profile.
To Reproduce
Steps to reproduce the behavior:
Run metaDataEvent() in NostrExamples.java
Expected behavior
Successfully updated profile.
"Causes and solutions"
The member variable profile in MetadataEvent is missing annotation "@JsonIgnore".
Add @JsonIgnore to profile in MetadataEvent.java.
Would it be possible to add the #nostr topic to this repo ?
I'll show up in this nice list here:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.