Feature 3: Sign and Verify Posts
In this feature, we have introduced a couple new lnd endpoints, SignMessage and VerifyMessage. These can be useful in cases where one user wants to be certain that some content has not been altered by a third-party. Following our mantra of “Can’t Be Evil”, we want to ensure our users that we have not tampered with the posts they author. So when a user creates a post, we will sign the message using their node and store the signature. If another user wants to verify that the post has not been modified, they will verify the signature using their own node.
In addition to verifying signatures, we took this opportunity to remove the user-specified usernames for each post. Instead we use the node’s alias for this field.
Let’s go to the feat-3a branch to see what’s changed.
git checkout feat-3aReplace username field with the node’s alias instead
To use the alias instead of a user-specified username, we needed to fetch the alias when the post is submitted to the backend and store it in the username field of the post. Then we need to remove the username field from the frontend flow that creates a post. As usual, we’ll start by updating the backend first then work our way up to the UI.
source: /backend/routes.ts
export const createPost = async (req: Request, res: Response) => {
const { token, title, content } = req.body;
const rpc = nodeManager.getRpc(token);
const { alias } = await rpc.getInfo();
const post = await db.createPost(alias, title, content);
res.status(201).send(post);
};We updated the createPost() route handler to get the alias using lnd’s getInfo() endpoint. Then we pass the alias to the db.createPost() function instead of the username received from the client. Notice that we no longer take the username from req.body as we do not require the client to send this value anymore. Instead, this handler expects to receive the node’s token, which will be automatically provided after the user connects their node.
source: /src/lib/api.ts
On the frontend, we removed the username parameter in the API wrapper’s createPost() function since the backend no longer needs this info.
source: /src/store/store.ts
In the mobx store, we removed the username parameter as well.
source: /src/pages/CreatepPost.tsx
Finally, in the CreatePost component, we removed the username state variable and associated field from the form.

Now when you visit the Create a Post screen in the browser, you will only see form fields to collect the Post’s title and content.

When you click submit, the new post will appear on the main screen with the subtitle “Posted by alice”. It set the username of the post to the alias of the node correctly.
Sign the message content when the post is created
Using lnd to sign a message is pretty straightforward. We just need to call the SignMessage endpoint with the message content in a specific format.
Checkout the feat-3b branch to see what’s changed.
source: /src/shared/types.ts
We’ll need to add a couple more fields to our Post model to store the signature and the node’s pubkey. These values are needed when another user wants to confirm that the signature is valid.
source: /backend/posts-db.ts
The createPost() function in the PostsDb class needed to be updated to add parameters for signature and pubkey, which are saved directly in the post.
Note: since we are modifying the schema of the Post model, you should delete the /db.json file now. Any posts that were created without these new fields will cause the app to throw errors when we run it the next time.
source: /backend/routes.ts
The final step on the backend is to update the createPost() route handler to sign the message using lnd’s SignMessage endpoint, then pass the signature and pubkey to the database to store for later.
source: /db.json
Now if you create a new post, then open the /db.json file in your editor, you should see the new post listed with the pubkey and signature.
With these changes, the backend now supports signing all new posts when they are created. Our last step in this feature is to allow users to verify the signature using their node.
Add button to verify a post’s signature
Verifying a Post’s signature is very similar to signing a message. We’ll just need to make use of lnd’s VerifyMessage endpoint, giving it the post’s content and signature. It will return a valid flag set to true as well as the pubkey of the signing node which we can compare to the pubkey stored with the post record to confirm the signature is valid.
Checkout the feat-3c branch to see what’s changed.
source: /src/shared/types.ts
We had to update the Post type to include a verified flag which will be false by default. We will switch it to true when another user verifies the content.
source: /backend/posts-db.ts
Next, we’ve added a new verifyPost() function to the PostsDb class. This function just sets the verified flag to true for a specified post.
source: /backend/index.ts
source: /backend/routes.ts
In the routes.ts file we’ve added the verifyPost() route handler and mapped it to the url in index.ts. This is where the bulk of the logic for verification is. There is a bunch going on here so let’s walk through it step by step.
Get the
idof the post from the url and the verifying user’stokenfrom the request bodyFind the post in the DB using the
idFind the node record using the
tokenof the user performing the verificationWe do not want to allow a user to verify their own posts, so we compare the
pubkeyof the node that signed this post with thepubkeyof the verifying user’s node. If they are the same, we throw an errorWith the basic validation done, now we can get the RPC connection of the verifying node and call the VerifyMessage endpoint, passing it the base64 encoded message and the signature stored in the post record
The verifyMessage endpoint will return two values:
validis a boolean flag indicating if the signature is validpubkeyis the pubkey of the node that signed the message. It is recovered from the signature
To confirm the signature is valid, we must ensure that the
validflag is true and also that the responsepubkeymatches the pubkey of the node that created the post. It is possible that another node can sign this message and produce a valid signature, so we need to check both of these conditions.Finally, if all of the verification checks pass, we call
verifyPost()in thePostsDbclass to set the post’sverifiedflag to true and return the updated post to the client
This completes all of the changes we need to make on the backend. Now let’s move to the frontend to implement verifying posts from the UI.
source: /src/lib/api.ts
In our API wrapper module, we added the verifyPost() function to make the http request to the backend.
source: /src/store/store.ts
In the mobx store, we added a new verifyPost() function which calls the API wrapper to make the http request, then updates the app state with the modified post record that is returned.
source: /src/components/PostCard.tsx
In the PostCard component, we’ve made a few updates for post verification:
In the post’s subtitle, we display that the post was signed by the user if there is a
signaturepresent.Also in the subtitle, it displays a badge with the text “verified” if the post’s
verifiedflag is true.Next to the “Upvote” button we render a “Verify Signature” button. This is a new component that we’ll explain below.
source: /src/components/VerifyButton.tsx
We created a new VerifyButton component which is pretty simple. If the post is not verified, it renders a button on the screen. When the button is clicked, it calls the store.verifyPost() function to initiate the signature verification.

Refresh the page in your browser and create a couple posts. You will now see the updates we’ve made. The post subtitles display that the posts are signed and there is a “Verify Signature” button. If you click on the button, you will receive an error message stating “You cannot verify your own posts!”. This is the intended behavior as we do not want to allow users to verify their own posts.

To test the Verify Signature feature, you’ll need to disconnect and reconnect using a different node, such as carol. Then you’ll be able to click on the “Verify Signature” button and see the “verified” badge now displayed.
We have now completed this feature. Next, we are going to take on our biggest improvement. We’ll implement making payments over Lightning in order to upvote a post.
Last updated
Was this helpful?