Nostred: Difference between revisions
(12 intermediate revisions by the same user not shown) | |||
Line 14: | Line 14: | ||
**** Is the signer reply blacklisted? | **** Is the signer reply blacklisted? | ||
**** Do I have history or other to trust signer for reply? | **** Do I have history or other to trust signer for reply? | ||
* [[NostredCommentStructure]] | |||
= Examples = | = Examples = | ||
== Community Description == | == Community Description == | ||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
Line 78: | Line 80: | ||
nevent1qqsfwym8w0wj6jptw95yppwx5vlduh5970x5zqjz4kelkucvyqdphvgpzdmhxw309akx7cmpd35x7um58gmnwdeh9w968t | nevent1qqsfwym8w0wj6jptw95yppwx5vlduh5970x5zqjz4kelkucvyqdphvgpzdmhxw309akx7cmpd35x7um58gmnwdeh9w968t | ||
$ python bob_test.py get -r ws://localhost:7777 nevent1qqsfwym8w0wj6jptw95yppwx5vlduh5970x5zqjz4kelkucvyqdphvgpzdmhxw309akx7cmpd35x7um58gmnwdeh9w968t | $ python bob_test.py get -r ws://localhost:7777 nevent1qqsfwym8w0wj6jptw95yppwx5vlduh5970x5zqjz4kelkucvyqdphvgpzdmhxw309akx7cmpd35x7um58gmnwdeh9w968t | ||
</pre> | |||
The replies were actually failing with the following message in the Strfry log. Need to look at why the client isn't reporting the failure, and where it's getting that event ID from. | |||
<pre> | |||
2023-10-10 02:05:53.063 (85038.540s) [Websocket ]INFO| [20] Connect from 127.0.0.1 compression=Y sliding=Y | |||
2023-10-10 02:05:53.125 (85038.602s) [Ingester 2 ]INFO| Rejected invalid event: uneven size input to from_hex | |||
2023-10-10 02:05:53.171 (85038.648s) [Websocket ]INFO| [20] Disconnect from 127.0.0.1 (1000/) UP: 120b (7.5% compressed) DN: 625b (30.7% compressed) | |||
</pre> | |||
Looks like Strfry does not like unpadded hex, which I'm guessing was sent in by aionostr: | |||
<pre> | |||
strfry$ more golpe/external/hoytech-cpp/hoytech/hex.h | |||
... | |||
if ((input.length() % 2) != 0) { | |||
if (!allowUnevenSize) throw hoytech::error("uneven size input to from_hex"); | |||
std::string padded; // does a copy if given non-even number of hex digits | |||
padded += '0'; | |||
padded += input; | |||
input = padded; | |||
} | |||
... | |||
</pre> | |||
AHA! It's the hex message ID I have to send back, not the base 32 nevent id: | |||
<pre> | |||
$ python bob_test.py send -r ws://localhost:7777 --content "Nostred2" --kind 1 --private-key nsec1dgg7d6e0g2484twl9ygntc24ueehm44frrc8rc93vcvun04gmp9qgufd4g --tags '[["a","34550:npub10jlc40w2mexjzmhce54n8w3z2euemqdwpghg3f7lvxrunr7dgvasm0nurp:Nostred","ws://localhost:7777"]]' | |||
3ab5991581bb23ebe51a24918c86abd5915cfec67225ec7d8b97542b84fa6e29 | |||
nevent1qqsr4dvezkqmkgltu5dzfyvvs64aty2ulmr8yf0v0k9ew4ptsnaxu2gpzdmhxw309akx7cmpd35x7um58gmnwdehy7k9rs | |||
$ python bob_test.py get -r ws://localhost:7777 nevent1qqsr4dvezkqmkgltu5dzfyvvs64aty2ulmr8yf0v0k9ew4ptsnaxu2gpzdmhxw309akx7cmpd35x7um58gmnwdehy7k9rs | |||
{"id":"3ab5991581bb23ebe51a24918c86abd5915cfec67225ec7d8b97542b84fa6e29","pubkey":"7cbf8abdcade4d216ef8cd2b33ba2256799d81ae0a2e88a7df6187c98fcd433b","created_at":1696905392,"kind":1,"tags":[["a","34550:npub10jlc40w2mexjzmhce54n8w3z2euemqdwpghg3f7lvxrunr7dgvasm0nurp:Nostred","ws://localhost:7777"]],"content":"Nostred2","sig":"eb148e6804e4e1b896adfd5c7e9c399d8e029a5010ee35547ab9eaab356d8f0524a6da99a15162463c3a1205062621da4b3001422b9e6ba7220c67d51f1dc474"} | |||
$ python bob_test.py send -r ws://localhost:7777 --content "Grumble" --kind 1 --private-key nsec1dgg7d6e0g2484twl9ygntc24ueehm44frrc8rc93vcvun04gmp9qgufd4g --tags '[["a","34550:npub10jlc40w2mexjzmhce54n8w3z2euemqdwpghg3f7lvxrunr7dgvasm0nurp:Nostred","ws://localhost:7777"],["e", "3ab5991581bb23ebe51a24918c86abd5915cfec67225ec7d8b97542b84fa6e29", ""]]' | |||
3346dce2124ae5cf674a0a0d427543a4d35fa592fcdf0dd078cff47806df432d | |||
nevent1qqsrx3kuugfy4ew0va9q5r2zw4p6f56l5kf0ehcd6puvlarcqm05xtgpzdmhxw309akx7cmpd35x7um58gmnwdeh79mhys | |||
$ python bob_test.py get -r ws://localhost:7777 nevent1qqsrx3kuugfy4ew0va9q5r2zw4p6f56l5kf0ehcd6puvlarcqm05xtgpzdmhxw309akx7cmpd35x7um58gmnwdeh79mhys | |||
{"id":"3346dce2124ae5cf674a0a0d427543a4d35fa592fcdf0dd078cff47806df432d","pubkey":"7cbf8abdcade4d216ef8cd2b33ba2256799d81ae0a2e88a7df6187c98fcd433b","created_at":1696905458,"kind":1,"tags":[["a","34550:npub10jlc40w2mexjzmhce54n8w3z2euemqdwpghg3f7lvxrunr7dgvasm0nurp:Nostred","ws://localhost:7777"],["e","3ab5991581bb23ebe51a24918c86abd5915cfec67225ec7d8b97542b84fa6e29",""]],"content":"Grumble","sig":"de9f6b5737e4d97f270b7331d780c0c12ce3fe09f0804ae03bfe1025284100b3158f07a20199661e95242b007c6c7b2d1d556008852ef714d2d29795446e988e"} | |||
</pre> | </pre> | ||
I don't love it. How do I get that hex ID on the client side? I'm guessing it's generated on the server side, cuz why would the server let clients generate their own message IDs? But I could be wrong, and maybe Strfry returns the message ID in the response and AIONostr just doesn't display it (or doesn't display it as hex). | |||
Yeah - or I could read the line before the base32 NIP-19 form of the id. You know, the previous line which is suspiciously hex looking. :D | |||
== Post Approval == | == Post Approval == |
Latest revision as of 21:50, 12 October 2023
Overview
Nostred is a topical threaded messaging system that treats centralized censorship as damage and routes around it. Decentralized censorship (aka: popularity, zeitgeist) is just a thing that happens. Governments, corporations, oligarchs, and madmen attempt to influence the direction of decentralized censorship.
Links
- NIP-10, Threaded Discussions: https://github.com/nostr-protocol/nips/blob/master/10.md
- NIP-72, Reddit Style Communities: https://github.com/nostr-protocol/nips/blob/master/72.md
- Combining NIP-72 with an automod filter in Strfry should be very doable.
- Is it a top level post?
- Is the signer top-level whitelisted?
- Is the signer top-level blacklisted?
- Do I have history or other to trust signer for top level?
- Is it a reply? Is the signer reply-approved?
- Is the signer reply whitelisted?
- Is the signer reply blacklisted?
- Do I have history or other to trust signer for reply?
- Is it a top level post?
- Combining NIP-72 with an automod filter in Strfry should be very doable.
- NostredCommentStructure
Examples
Community Description
{
"id": "<32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>",
"pubkey": "<32-bytes lowercase hex-encoded public key of the event creator>",
"created_at": <Unix timestamp in seconds>,
"kind": 34550,
"tags": [
["d", "<Community name>"],
["description", "<Community description>"],
["image", "<Community image url>", "<Width>x<Height>"],
//.. other tags relevant to defining the community
// moderators
["p", "<32-bytes hex of a pubkey1>", "<optional recommended relay URL>", "moderator"],
["p", "<32-bytes hex of a pubkey2>", "<optional recommended relay URL>", "moderator"],
["p", "<32-bytes hex of a pubkey3>", "<optional recommended relay URL>", "moderator"],
// relays used by the community (w/optional marker)
["relay", "<relay hosting author kind 0>", "author"],
["relay", "<relay where to send and receive requests>", "requests"],
["relay", "<relay where to send and receive approvals>", "approvals"],
["relay", "<relay where to post requests to and fetch approvals from>"]
]
}
New Post Request
Satisfies two NIPs:
- https://github.com/nostr-protocol/nips/blob/master/10.md#marked-e-tags-preferred
- https://github.com/nostr-protocol/nips/blob/master/72.md#new-post-request
{
"id": "<32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>",
"pubkey": "<32-bytes lowercase hex-encoded public key of the event creator>",
"created_at": <Unix timestamp in seconds>,
"kind": 1,
"tags": [
["a", "34550:<Community event author pubkey>:<d-identifier of the community>", "<Optional relay url>"],
["e", "<event-id>", "<relay-url>", "root"], // required for all replies, identifies the root post
["e", "<event-id>", "<relay-url>", "reply"], // optional, if this is a reply to a reply
],
"content": "<My content>"
}
Testing
$ python bob_test.py send -r ws://localhost:7777 --content "Nostred" --kind 1 --private-key nsec1dgg7d6e0g2484twl9ygntc24ueehm44frrc8rc93vcvun04gmp9qgufd4g --tags '[["a","34550:npub10jlc40w2mexjzmhce54n8w3z2euemqdwpghg3f7lvxrunr7dgvasm0nurp:Nostred","ws://localhost:7777"]]' 5b8440d62761bab91c36708a6143aa51a725a1f1fd320a5d580ae818455d1906 nevent1qqs9hpzq6cnkrw4ersm8pznpgw49rfe958cl6vs2t4vq46qcg4w3jpspzdmhxw309akx7cmpd35x7um58gmnwdehzt4mtw $ python bob_test.py get -r ws://localhost:7777 nevent1qqs9hpzq6cnkrw4ersm8pznpgw49rfe958cl6vs2t4vq46qcg4w3jpspzdmhxw309akx7cmpd35x7um58gmnwdehzt4mtw {"id":"5b8440d62761bab91c36708a6143aa51a725a1f1fd320a5d580ae818455d1906","pubkey":"7cbf8abdcade4d216ef8cd2b33ba2256799d81ae0a2e88a7df6187c98fcd433b","created_at":1696902240,"kind":1,"tags":[["a","34550:npub10jlc40w2mexjzmhce54n8w3z2euemqdwpghg3f7lvxrunr7dgvasm0nurp:Nostred","ws://localhost:7777"]],"content":"Nostred","sig":"cbe2434cf9d8790df669afbe0bb8a435999bef4539fa6a1c725fb0bda9073e97b1531bdedbcca7523fa5a375e4f472671047cde51c4870041e7971c6d218aecd"} 5b8440d62761bab91c36708a6143aa51a725a1f1fd320a5d580ae818455d1906 nevent1qqs9hpzq6cnkrw4ersm8pznpgw49rfe958cl6vs2t4vq46qcg4w3jpspzdmhxw309akx7cmpd35x7um58gmnwdehzt4mtw $ python bob_test.py send -r ws://localhost:7777 --content "Nostred" --kind 1 --private-key nsec1dgg7d6e0g2484twl9ygntc24ueehm44frrc8rc93vcvun04gmp9qgufd4g --tags '[["a","34550:npub10jlc40w2mexjzmhce54n8w3z2euemqdwpghg3f7lvxrunr7dgvasm0nurp:Nostred","ws://localhost:7777"],["e", "nevent1qqs9hpzq6cnkrw4ersm8pznpgw49rfe958cl6vs2t4vq46qcg4w3jpspzdmhxw309akx7cmpd35x7um58gmnwdehzt4mtw", "ws://localhost:7777", "root"]]' 18334e45d9493d754016147a3546c340b6fca58f1695611197d3311f5dcc1312 nevent1qqspsv6wghv5j0t4gqtpg734gmp5pdhu5k83d9tpzxtaxvglthxpxyspzdmhxw309akx7cmpd35x7um58gmnwdeh5erhwd $ python bob_test.py send -r ws://localhost:7777 --content "Nostred" --kind 1 --private-key nsec1dgg7d6e0g2484twl9ygntc24ueehm44frrc8rc93vcvun04gmp9qgufd4g --tags '[["a","34550:npub10jlc40w2mexjzmhce54n8w3z2euemqdwpghg3f7lvxrunr7dgvasm0nurp:Nostred","ws://localhost:7777"],["e", "nevent1qqs9hpzq6cnkrw4ersm8pznpgw49rfe958cl6vs2t4vq46qcg4w3jpspzdmhxw309akx7cmpd35x7um58gmnwdehzt4mtw", "ws://localhost:7777", "root"],["e", "nevent1qqspsv6wghv5j0t4gqtpg734gmp5pdhu5k83d9tpzxtaxvglthxpxyspzdmhxw309akx7cmpd35x7um58gmnwdeh5erhwd", "ws://localhost:7777", "reply"]]' 97136773dd2d482b71684085c6a33ede5e85f3cd410242adb3fb730c201a1bb1 nevent1qqsfwym8w0wj6jptw95yppwx5vlduh5970x5zqjz4kelkucvyqdphvgpzdmhxw309akx7cmpd35x7um58gmnwdeh9w968t $ python bob_test.py get -r ws://localhost:7777 nevent1qqsfwym8w0wj6jptw95yppwx5vlduh5970x5zqjz4kelkucvyqdphvgpzdmhxw309akx7cmpd35x7um58gmnwdeh9w968t
The replies were actually failing with the following message in the Strfry log. Need to look at why the client isn't reporting the failure, and where it's getting that event ID from.
2023-10-10 02:05:53.063 (85038.540s) [Websocket ]INFO| [20] Connect from 127.0.0.1 compression=Y sliding=Y 2023-10-10 02:05:53.125 (85038.602s) [Ingester 2 ]INFO| Rejected invalid event: uneven size input to from_hex 2023-10-10 02:05:53.171 (85038.648s) [Websocket ]INFO| [20] Disconnect from 127.0.0.1 (1000/) UP: 120b (7.5% compressed) DN: 625b (30.7% compressed)
Looks like Strfry does not like unpadded hex, which I'm guessing was sent in by aionostr:
strfry$ more golpe/external/hoytech-cpp/hoytech/hex.h ... if ((input.length() % 2) != 0) { if (!allowUnevenSize) throw hoytech::error("uneven size input to from_hex"); std::string padded; // does a copy if given non-even number of hex digits padded += '0'; padded += input; input = padded; } ...
AHA! It's the hex message ID I have to send back, not the base 32 nevent id:
$ python bob_test.py send -r ws://localhost:7777 --content "Nostred2" --kind 1 --private-key nsec1dgg7d6e0g2484twl9ygntc24ueehm44frrc8rc93vcvun04gmp9qgufd4g --tags '[["a","34550:npub10jlc40w2mexjzmhce54n8w3z2euemqdwpghg3f7lvxrunr7dgvasm0nurp:Nostred","ws://localhost:7777"]]' 3ab5991581bb23ebe51a24918c86abd5915cfec67225ec7d8b97542b84fa6e29 nevent1qqsr4dvezkqmkgltu5dzfyvvs64aty2ulmr8yf0v0k9ew4ptsnaxu2gpzdmhxw309akx7cmpd35x7um58gmnwdehy7k9rs $ python bob_test.py get -r ws://localhost:7777 nevent1qqsr4dvezkqmkgltu5dzfyvvs64aty2ulmr8yf0v0k9ew4ptsnaxu2gpzdmhxw309akx7cmpd35x7um58gmnwdehy7k9rs {"id":"3ab5991581bb23ebe51a24918c86abd5915cfec67225ec7d8b97542b84fa6e29","pubkey":"7cbf8abdcade4d216ef8cd2b33ba2256799d81ae0a2e88a7df6187c98fcd433b","created_at":1696905392,"kind":1,"tags":[["a","34550:npub10jlc40w2mexjzmhce54n8w3z2euemqdwpghg3f7lvxrunr7dgvasm0nurp:Nostred","ws://localhost:7777"]],"content":"Nostred2","sig":"eb148e6804e4e1b896adfd5c7e9c399d8e029a5010ee35547ab9eaab356d8f0524a6da99a15162463c3a1205062621da4b3001422b9e6ba7220c67d51f1dc474"} $ python bob_test.py send -r ws://localhost:7777 --content "Grumble" --kind 1 --private-key nsec1dgg7d6e0g2484twl9ygntc24ueehm44frrc8rc93vcvun04gmp9qgufd4g --tags '[["a","34550:npub10jlc40w2mexjzmhce54n8w3z2euemqdwpghg3f7lvxrunr7dgvasm0nurp:Nostred","ws://localhost:7777"],["e", "3ab5991581bb23ebe51a24918c86abd5915cfec67225ec7d8b97542b84fa6e29", ""]]' 3346dce2124ae5cf674a0a0d427543a4d35fa592fcdf0dd078cff47806df432d nevent1qqsrx3kuugfy4ew0va9q5r2zw4p6f56l5kf0ehcd6puvlarcqm05xtgpzdmhxw309akx7cmpd35x7um58gmnwdeh79mhys $ python bob_test.py get -r ws://localhost:7777 nevent1qqsrx3kuugfy4ew0va9q5r2zw4p6f56l5kf0ehcd6puvlarcqm05xtgpzdmhxw309akx7cmpd35x7um58gmnwdeh79mhys {"id":"3346dce2124ae5cf674a0a0d427543a4d35fa592fcdf0dd078cff47806df432d","pubkey":"7cbf8abdcade4d216ef8cd2b33ba2256799d81ae0a2e88a7df6187c98fcd433b","created_at":1696905458,"kind":1,"tags":[["a","34550:npub10jlc40w2mexjzmhce54n8w3z2euemqdwpghg3f7lvxrunr7dgvasm0nurp:Nostred","ws://localhost:7777"],["e","3ab5991581bb23ebe51a24918c86abd5915cfec67225ec7d8b97542b84fa6e29",""]],"content":"Grumble","sig":"de9f6b5737e4d97f270b7331d780c0c12ce3fe09f0804ae03bfe1025284100b3158f07a20199661e95242b007c6c7b2d1d556008852ef714d2d29795446e988e"}
I don't love it. How do I get that hex ID on the client side? I'm guessing it's generated on the server side, cuz why would the server let clients generate their own message IDs? But I could be wrong, and maybe Strfry returns the message ID in the response and AIONostr just doesn't display it (or doesn't display it as hex).
Yeah - or I could read the line before the base32 NIP-19 form of the id. You know, the previous line which is suspiciously hex looking. :D
Post Approval
Story
Using Cyberpunk 2077 as a rough framing device. Actors are not meant to be exact copies from the game, but to act as rough parallels.
Imagine a world in which amoral corporations and their oligarchic founders have extreme influence over government. People have become disenfranchised and some have begun to radicalize. Those people want to use Nostred for messaging to advance what they believe is in the best interests of society.
Nostred is a topical threaded messaging system that treats centralized censorship as damage and routes around it. Decentralized censorship (aka: popularity, zeitgeist) is just a thing that happens. Governments, corporations, oligarchs, and madmen attempt to influence the direction of decentralized censorship.
People
V
The object of everyone's machinations. V has no axe, a priori, to grind. Everyone else is trying to present, suppress, or influence information that V sees to get her to act as they see fit.
Punchin' Judy
Neutral good humanist. Wants everyone to be happy. Sees the best in people. Does not trust Arasaka (nor, by extension, Militech).
Johnny Silverhand
Chaotic good. Justice warrior with an emphasis on "warrior". Asymmetric urban warfare specialist.
Takahara
Lawful good. Believes the system would be good if it weren't for the few baddies in positions of power. Assassin.
Wakako
Chaotic neutral. Does for Wakako.
Orgs
Arasaka
Amoral corporation, only cares about money and power. Law is a constraint that must be worked around or manipulated - or in the worst possible case, followed.
Pacifica
Collective of counter-culture that is obsessed with money and power. Basically Arasaka, but Militech doesn't like them.
The Coyotes
Collective of counter-culture that is benevolent. Works against the big bads (Arasaka and, by extension, often Militech).
Militech
Abstract representation of government force. Often aligns with Arasaka, shot through with people of various conflicted interests; corrupt or idealistic, malevolent or benevolent, psychotic or rational, &c.
Fixers
Not truly an org, but a tag for the collection of indies who are just in it for the money.
Conflict
Arasaka Versus Society
Arasaka wants to control reality for Arasaka's interests. Uses law and influence to manipulate perception of reality.
Militech Versus Society
Militech wants to control society for good, with good defined in occasionally dystopian ways. Creates and enforces law for the benefit of those it (mis)perceives as lawful.
Stories
Silverhand Rabble Rousing
Johnny incites people to go to a flash-mob street performance that will turn into a riot against Arasaka. Messaging via Nostr.
Judy opposes because riots might get people hurt. Arasaka enlists Militech to suppress the messaging.
Arasaka Suppression
- Arasaka starts by finding unlawful material carried by the relays, and asking Militech to shut them down.
- Later, Arasaka plants copyrighted material, when the relays stop doing illegal things.
- Arasaka gets speech that incites violence ruled illegal and just cause for relay takedown.
Are these things illegal? The story has to be credible. Find the actual legal status.
- Section 230: https://en.wikipedia.org/wiki/Section_230
- Argument for Duty of Care: https://hbr.org/2021/08/its-time-to-update-section-230
Takahara Assassination
Takahara wants to knock off a VP and his cronies. Crowd-sources the solution and enlists actors via Nostr.
Arasaka enlists Militech to detect, unmask, and arrest Takahara.