Skip to main content

Notary Express.js Application

Length: Short
Complexity:
Duration: 5 minutes

Overview

This sample application represents a blockchain-based notary service. The service stores a SHA256 hash of a document on the mintBlue blockchain. To keep the example simple, you can only enter a string. However, you can easily extend the application to accept files and other data types. The example uses the Express framework to serve a simple frontend where you can enter a string.

Prerequisites

You have two options to run the code:

  1. Create a project on your machine and copy the code
  2. Use the code in the CodeSandBox

How does the notary application work

Submitting a document to the notary application generates a unique digital fingerprint from your document's contents, known as a SHA256 hash. This hash serves as a secure and tamper-proof representation of your document.

The application then checks its records on the Bitcoin blockchain to determine if this specific hash already exists. If it's a new hash, the application creates a transaction to add this hash to the Bitcoin blockchain. Once recorded on the blockchain, this hash becomes immutable, meaning it cannot be altered or deleted.

If the hash already exists on the blockchain, the application retrieves it along with the timestamp of its initial creation. This timestamp is crucial, providing the exact date and time when the document was first notarized.

The significance of this process lies in its ability to prove the authenticity and originality of a document. Since the SHA256 hash is unique to each document, and the blockchain's records are immutable and publicly verifiable, anyone can check the authenticity of a document by comparing its hash with the one stored on the blockchain. This ensures that the document has not been altered since its original notarization, thereby providing a robust method for document verification and proof of authenticity.

const express = require("express");
const bodyParser = require('body-parser');

const app = express();
const port = 3000;

const { Mintblue, utils } = require("@mintblue/sdk");

const sdkToken = "<YOUR-SDK-TOKEN>";
let projectId = "<YOUR-PROJECT-ID>";
let client;

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.post("/", async (req, res) => {
  // calculate data hash
  const byteArray = await utils.sha256(req.body.data);
  let hash = Buffer.from(byteArray).toString("base64");

  // look up hash in notary
  let result = await findNotaryRecord(hash);
  if (result) {
    // notary record found, show result
    res.send(
      `Found notary record:<br />Transaction ID: ${result.txid}<br />SHA256: ${result.hash}<br />Timestamp: ${result.timestamp}`
    );
  } else {
    // no notary record found, create new record and show
    const { txid } = await client.createTransaction({
      project_id: projectId,
      outputs: [
        {
          type: "data",
          value: hash,
        },
      ],
    });
    const result = await findNotaryRecord(hash);
    res.send(
      `Created notary record:<br />Transaction ID: ${result.txid}<br />SHA256: ${result.hash}<br />Timestamp: ${result.timestamp}`
    );
  }
});

app.get("/", (req, res, next) => {
  // present simple form allowing the user to input a string
  res.send(`
    <form method="POST" action="/">
        <input type="text" name="data" placeholder="data">
        <input type="submit">
    </form>
  `);
});

const getNotary = async () => {
  // get notary transactions
  const txs = await client.listTransactions({ project_id: projectId });
  const notary = [];
  for (tx of txs) {
    // fetch notary record payload
    const payload = await client.getTransaction({
        txid: tx.txid,
        parse: true,
    });

    notary.push({
      txid: tx.txid,
      hash: payload.outputs[0].value,
      timestamp: tx.published_at,
    });
  }

  return notary;
};

// find hash in notary records
const findNotaryRecord = async (hash) => {
  const hashes = await getNotary();

  const result = hashes.find((el) => {
    return el.hash === hash;
  });
  return result;
};

// set up express listener
app.listen(port, async () => {
  client = await Mintblue.create({ token: sdkToken });
  console.log(`Notary app listening on port ${port}`);
});

To use this code, make sure to initialize your project with npm init -y and install the mintBlue SDK, express, and body-parser dependencies.

npm install --save @mintblue/sdk express body-parser

Next, let's run the example.

How do you run the notary application

Make sure to replace the <YOUR-SDK-TOKEN> with your SDK Access Token and <YOUR-PROJECT-ID> with your project ID. If you are running the code on your machine, name the file notary.js.

To run the example, you can execute the file with node.

node notary.js

The command will spin up an Express server and will open the application in your browser. If it doesn't open the application, navigate to http://localhost:3000. The application looks like this:

Let's enter the input string mydocument. We'll get the following output.

Created notary record:
Transaction ID: ec088dd8cc33373bea50a4955fa61a3a6316593bad0563155c53b47e1a5838e0
SHA256: JUeAIJvVk0b2cu/E7AX+6crm/G4wavAk0z3Y6lGabcM=
Timestamp: 2023-12-20T15:26:07.650Z

Now, let's enter the same string mydocument to verify if it found the document to prove its notarization. The app should tell us it has found the notary record. Here's the output:

Found notary record:
Transaction ID: ec088dd8cc33373bea50a4955fa61a3a6316593bad0563155c53b47e1a5838e0
SHA256: JUeAIJvVk0b2cu/E7AX+6crm/G4wavAk0z3Y6lGabcM=
Timestamp: 2023-12-20T15:26:07.650Z

✅ Want to learn more and play with code? Check out the Password manager application.