draft
optional
Comment updates contain mutable data associated with comments, like votes and replies. They are signed by a subplebbit and republished by a subplebbit every few minutes, if there has been a new vote or reply.
For example:
{
"cid": "QmXnEICVkZBHKgjtj7Vt63HWq3ZfPjcGTSPs79oXtfEZxc",
"upvoteCount": 10,
"downvoteCount": 5,
"replyCount": 3,
"replies": {"pages": {"top": {"comments": [<comment1>, <comment2>, <comment3>]}}},
"updatedAt": 1728174027,
"lastReplyTimestamp": 1728450341,
"lastChildCid": "QmXnEICVkZBHKgjtj7Vt63HWq3ZfPjcGTSPs79oXtfEZxc",
"protocolVersion": "1.0.0",
"signature": {
"signature": <base64>,
"publicKey": <base64>,
"type": "ed25519",
"signedPropertyNames": ["cid", "upvoteCount", "downvoteCount", "replyCount", "replies", "updatedAt", "lastReplyTimestamp", "lastChildCid", "protocolVersion"]
}
}
Required fields are:
cid
updatedAt
protocolVersion
signature
Optional fields are:
upvoteCount
downvoteCount
replyCount
replies
lastReplyTimestamp
lastChildCid
flair
spoiler
pinned
locked
removed
reason
author
edit
Comment updates can be fetched by their IPFS folder CID (content ID), for example by going to https://ipfsgateway.xyz/ipfs///update or https://ipfsgateway.xyz/ipfs/QmTFuY58c2w9WofMM9KshjUqNncX7EwDK7pV9TMf7aeg1G/QmTFuY58c2w9WofMM9KshjUqNncX7EwDK7pV9TMf7aeg1G/update
can be found in subplebbit.postUpdates.<timestamp-bucket>
.
can be calculated using this algorithm:
const secondsSincePublished = (Date.now() / 1000) - comment.timestamp
for (const timestampBucket in subplebbit.postUpdates) {
if (secondsSincePublished <= timestampBucket) {
return timestampBucket // found timestamp bucket
}
}
The purpose of timestamp buckets is to update folder CIDs of older posts less frequently to save resources.
Same as defined in PLIP-1.
For example:
{
"cid": "QmXnEICVkZBHKgjtj7Vt63HWq3ZfPjcGTSPs79oXtfEZxc",
"upvoteCount": 10,
"downvoteCount": 5,
"updatedAt": 1728174027,
"protocolVersion": "1.0.0",
"signature": {
"signature": <base64>,
"publicKey": <base64>,
"type": "ed25519",
"signedPropertyNames": ["cid", "upvoteCount", "downvoteCount", "updatedAt", "protocolVersion"]
}
}
For example:
{
"cid": "QmXnEICVkZBHKgjtj7Vt63HWq3ZfPjcGTSPs79oXtfEZxc",
"replyCount": 3,
"replies": {"pages": {"top": {"comments": [<comment1>, <comment2>, <comment3>]}}},
"updatedAt": 1728174027,
"lastReplyTimestamp": 1728450341,
"lastChildCid": "QmXnEICVkZBHKgjtj7Vt63HWq3ZfPjcGTSPs79oXtfEZxc",
"protocolVersion": "1.0.0",
"signature": {
"signature": <base64>,
"publicKey": <base64>,
"type": "ed25519",
"signedPropertyNames": ["cid", "replyCount", "replies", "updatedAt", "lastReplyTimestamp", "lastChildCid", "protocolVersion"]
}
}
Subplebbits may add some unsigned fields like comment.depth
, comment.previousCid
, comment.postCid
, etc. these fields must be ignored until validated through commentUpdate.signature
and commentUpdate.cid
.
commentUpdate.signature
must contain commentUpdate.cid
and commentUpdate.cid
must be equal to the comment cid for the unsigned comment fields to validated.
For example:
{
"title": "Breaking: The Sky Is Falling!",
"link": "https://cnn.com/the-sky-is-falling.html",
"subplebbitAddress": "news.eth",
"author": {"address": "john.eth"},
"timestamp": 1728174027,
"signature": {
"signature": <base64>,
"publicKey": <base64>,
"type": "ed25519",
"signedPropertyNames": ["title", "link", "subplebbitAddress", "author", "timestamp"]
},
// below not included in signature.signedPropertyNames, validated by commentUpdate.signature and commentUpdate.cid === comment CID
"depth": 0,
"previousCid": "QmXnEICVkZBHKgjtj7Vt63HWq3ZfPjcGTSPs79oXtfEZxc"
}
Comment was removed by a moderator.
For example:
{
"cid": "QmXnEICVkZBHKgjtj7Vt63HWq3ZfPjcGTSPs79oXtfEZxc",
"removed": true,
"updatedAt": 1728174027,
"protocolVersion": "1.0.0",
"signature": {
"signature": <base64>,
"publicKey": <base64>,
"type": "ed25519",
"signedPropertyNames": ["cid", "removed", "updatedAt", "protocolVersion"]
}
}
Comment was locked by a moderator.
For example:
{
"cid": "QmXnEICVkZBHKgjtj7Vt63HWq3ZfPjcGTSPs79oXtfEZxc",
"locked": true,
"updatedAt": 1728174027,
"protocolVersion": "1.0.0",
"signature": {
"signature": <base64>,
"publicKey": <base64>,
"type": "ed25519",
"signedPropertyNames": ["cid", "locked", "updatedAt", "protocolVersion"]
}
}
Comment was pinned by a moderator.
For example:
{
"cid": "QmXnEICVkZBHKgjtj7Vt63HWq3ZfPjcGTSPs79oXtfEZxc",
"pinned": true,
"updatedAt": 1728174027,
"protocolVersion": "1.0.0",
"signature": {
"signature": <base64>,
"publicKey": <base64>,
"type": "ed25519",
"signedPropertyNames": ["cid", "pinned", "updatedAt", "protocolVersion"]
}
}
Comment was edited by its author.
For example:
{
"cid": "QmXnEICVkZBHKgjtj7Vt63HWq3ZfPjcGTSPs79oXtfEZxc",
"edit": {
"commentCid": "QmXnEICVkZBHKgjtj7Vt63HWq3ZfPjcGTSPs79oXtfEZxc",
"content": "I made a mistake.",
"timestamp": 1728174027,
"author": {"address": "john.eth"},
"signature": {
"signature": <base64>,
"publicKey": <base64>,
"type": "ed25519",
"signedPropertyNames": ["commentCid", "content", "timestamp", "author"]
}
},
"updatedAt": 1728174027,
"protocolVersion": "1.0.0",
"signature": {
"signature": <base64>,
"publicKey": <base64>,
"type": "ed25519",
"signedPropertyNames": ["cid", "edit", "updatedAt", "protocolVersion"]
}
}
For example:
{
"cid": "QmXnEICVkZBHKgjtj7Vt63HWq3ZfPjcGTSPs79oXtfEZxc",
"author": {
"postScore": 103,
"replyScore": 252,
"lastCommentCid": "QmXnEICVkZBHKgjtj7Vt63HWq3ZfPjcGTSPs79oXtfEZxc",
"firstCommentTimestamp": 1728174027
},
"updatedAt": 1728174027,
"protocolVersion": "1.0.0",
"signature": {
"signature": <base64>,
"publicKey": <base64>,
"type": "ed25519",
"signedPropertyNames": ["cid", "author", "updatedAt", "protocolVersion"]
}
}