Chainpoint

Chainpoint is an open standard for creating a timestamp proof of any data, file, or series of events.

Anchor an unlimited amount of data to multiple blockchains. Verify the integrity and existence of data without relying on a trusted third-party.


...plus hundreds of others use Chainpoint.

How does Chainpoint work?

Chainpoint links a hash of your data to a blockchain and returns a timestamp proof. A Chainpoint service receives hashes which are aggregated together using a Merkle tree. The root of this tree is anchored in the Bitcoin and Ethereum blockchains. Throughout this process a Chainpoint proof is created and continually upgraded. The final Chainpoint proof defines a path of operations that cryptographically links your data to one or more blockchains.

What is a Chainpoint Proof?

A proof is a JSON-LD document, that contains the information to cryptographically verify a piece of data is anchored to a blockchain. It proves the data existed at time it was anchored. Chainpoint proofs can be verified without reliance on a trusted third party.


Chainpoint Proof Versions

The third major version of the Chainpoint proof specification is currently in testing and scheduled for release soon. A JSON schema validator is available.

Name Description
@context
string, required
the JSON-LD context for the proof
typestring, required the JSON-LD type definition
hashstring, required hash value between 40 and 128 hex characters. Must be even length.
hash_idstring, required a Version 1 UUID with embedded timestamp. Random number used as MAC input. Timestamp represents server time (UTC) of hash submission.
hash_submitted_atstring, required Human readable ISO 8601 timestamp extracted from time embedded in the hash_id
branches - an array of branch objects. Branches can be nested without limit and MUST be traversed only after executing 'ops'. (required only at root)
labelstring, optional text string representing the branch name
opsarray, optional an array of operations objects. Operations are performed in sequence to arrive at an intermediate hash prior to entering a nested branch.
branchesarray, optional nested array of branch objects. Each branch contains ops; labels and additional nested branches are optional.
ops - an array of operation objects (required under every 'branches' object)
lstring, optional left concatenate a value. If the value is a hexadecimal string, it will be read as a hexadecimal byte array, otherwise the string will be converted to its byte value assuming UTF-8 encoding.
rstring, optional right concatenate a value. If the value is a hexadecimal string, it will be read as a hexadecimal byte array, otherwise the string will be converted to its byte value assuming UTF-8 encoding.
opstring, optional an operation to perform on the current value combined with a previous 'l' or 'r' operation. Current operations: 'sha-224', 'sha-256', 'sha-384', 'sha-512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512', or the special purpose 'sha-256-x2' which applies 'sha-256' twice.
anchors - an array of anchor objects (required under every 'ops' object).
typestring, required one of 'cal' (Calendar), 'btc' (Bitcoin), or 'eth' (Ethereum) anchor types
anchor_idstring, required an identifier used to look up embedded anchor data. e.g. a Bitcoin transaction or block ID.
urisarray, optional an array of special purpose string URI's, each of which can be used to lookup and retrieve the exact hash resource required to validate this anchor. The URI MUST return only a Hexadecimal hash value as a string. The URI MUST also contain the 'anchor_id' value to lookup the URI resource. This strict requirement is to allow automated clients to retrieve and validate intermediate hashes when verifying a proof. The body value returned by the URI MUST be of even length and match the regex [a-fA-F0-9].

Example


// Note : This sample is for demonstration purposes only

{
  "@context": "https://w3id.org/chainpoint/v3",
  "type": "Chainpoint",
  "hash": "bdf8c9bdf076d6aff0292a1c9448691d2ae283f2ce41b045355e2c8cb8e85ef2",
  "hash_id": "5cf0a860-0f52-11e7-947d-7fde4e7ca024",
  "hash_submitted_at": "2017-03-23T11:30:33Z",
  "branches": [{
    "label": "root_branch",
    "ops": [{
        "l": "5cf0a860-0f52-11e7-947d-7fde4e7ca024"
      },
      {
        "op": "sha-256"
      },
      {
        "r": "72de6fe5c8f3505b58436c86b87d2cdf7fca3a2edb485f6642e18249cedf2d68"
      },
      {
        "op": "sha-256"
      },
      {
        "r": "ee0df617d253f12be5ab59b4b723c35aa88075df33ad0c46d8231c9df8de3d35"
      },
      {
        "op": "sha-256"
      },
      {
        "anchors": [{
          "type": "cal",
          "anchor_id": "1027",
          "uris": [
            "http://a.cal.chainpoint.org/1027/root",
            "http://b.cal.chainpoint.org/1027/root"
          ]
        }]
      }
    ],
    "branches": [{
        "label": "branch_01",
        "ops": [{
            "l": "72de6fe5c8f3505b58436c86b87d2cdf7fca3a2edb485f6642e18249cedf2d68"
          },
          {
            "op": "sha-256"
          },
          {
            "l": "09096dbc49b7909917e13b795ebf289ace50b870440f10424af8845fb7761ea5"
          },
          {
            "op": "sha-256"
          },
          {
            "l": "283d2558a4a3b7c56136984f9211de42637b58c41576ed8d9627bf5423c7966c"
          },
          {
            "op": "sha-256"
          },
          {
            "anchors": [{
              "type": "eth",
              "anchor_id": "d3e7ec84c3dbe86f7d9a8ea68ae4ded6c0b012be519f433a07f15bd612fb47a9"
            }]
          }
        ]
      },
      {
        "label": "branch_02",
        "ops": [{
            "l": "cb0dbbedb5ec5363e39be9fc43f56f321e1572cfcf304d26fc67cb6ea2e49faf"
          },
          {
            "op": "sha-256"
          },
          {
            "r": "cb0dbbedb5ec5363e39be9fc43f56f321e1572cfcf304d26fc67cb6ea2e49faf"
          },
          {
            "op": "sha-256"
          },
          {
            "l": "0100000001d94a7f924e49246a136a95ceb70b7c6758b2a65f7cca2b0fa144cbe7c39f217a010000006a4730440220504a4571c4263c83d51399ef14240a3bb06af7159fb6dbb6db182e7e7901edf802202942e98a20d295753155c5249a584f6261a6b31ce603720b7c37e0e71ba742070121035b690114679d44d75b75aa170e34596c94c778f589bcb9063b0e4e293fcacd1dffffffff020000000000000000226a20"
          },
          {
            "r": "7b0d3e00000000001976a9147003cc5915f6c23fd512b38daeeecfdde7a587e988ac00000000"
          },
          {
            "op": "sha-256-x2"
          },
          {
            "l": "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
          },
          {
            "op": "sha-256-x2"
          },
          {
            "anchors": [{
              "type": "btc",
              "anchor_id": "434702"
            }]
          }
        ]
      }
    ]
  }]
}
Name Description
@context the JSON-LD context for the receipt
type receipt type definition specifying hash method and version
targetHash hash value being anchored to the blockchain
merkleRoot merkle tree root value that is anchored to the blockchain
proof merkle proof establishing link from the targetHash to the merkleRoot
anchors
type anchor type definition specifying anchoring method
sourceId identifier, such as a transaction id, used to locate anchored data

Example

{
 "@context": "https://w3id.org/chainpoint/v2",
 "type": "ChainpointSHA256v2",
 "targetHash": "bdf8c9bdf076d6aff0292a1c9448691d2ae283f2ce41b045355e2c8cb8e85ef2",
 "merkleRoot": "51296468ea48ddbcc546abb85b935c73058fd8acdb0b953da6aa1ae966581a7a",
 "proof": [
   {
     "left": "bdf8c9bdf076d6aff0292a1c9448691d2ae283f2ce41b045355e2c8cb8e85ef2"
   },
   {
     "left": "cb0dbbedb5ec5363e39be9fc43f56f321e1572cfcf304d26fc67cb6ea2e49faf"
   },
   {
     "right": "cb0dbbedb5ec5363e39be9fc43f56f321e1572cfcf304d26fc67cb6ea2e49faf"
   }
 ],
 "anchors": [
   {
     "type": "BTCOpReturn",
     "sourceId": "f3be82fe1b5d8f18e009cb9a491781289d2e01678311fe2b2e4e84381aafadee"
   }
 ]
}

Receipt Types

Receipt type values indicate the hash type and version of the receipt. The following values are supported.

Type Description
ChainpointSHA224v2 Chainpoint 2.0 receipt using SHA-224
ChainpointSHA256v2 Chainpoint 2.0 receipt using SHA-256
ChainpointSHA384v2 Chainpoint 2.0 receipt using SHA-384
ChainpointSHA512v2 Chainpoint 2.0 receipt using SHA-512
ChainpointSHA3-224v2 Chainpoint 2.0 receipt using SHA3-224
ChainpointSHA3-256v2 Chainpoint 2.0 receipt using SHA3-256
ChainpointSHA3-384v2 Chainpoint 2.0 receipt using SHA3-384
ChainpointSHA3-512v2 Chainpoint 2.0 receipt using SHA3-512

Anchor Types

Anchor type values indicate the method and location of the anchored data. The following values are supported. Support for additional methods is planned.

Type Description
BTCOpReturn Anchored to a Bitcoin transaction within an OP_RETURN output.
ETHData Anchored to an Ethereum transaction within the data field.
Name Description
Header
chainpoint_version version of the Chainpoint standard
hash_type hashing algorithm used to encrypt target data (sha­256)
merkle_root root of the Merkle Tree that is published in the blockchain
tx_id blockchain transaction id
timestamp non­authoritative Unix timestamp of the target
Target
target_hash hash of the target that is being recorded in the blockchain
target_proof Merkle proof used to prove target_hash is part of Merkle tree
target_URI (optional) path to the target
Extra
custom (optional) array of user defined key value pairs

Example

{
  "header": {
    "chainpoint_version": "1.1",
    "hash_type": "SHA-256",
    "merkle_root": "8dbd52c5ff89b70711b06c143520ef4eb295c51040757c7a4ab56303f0f6b68f",
    "tx_id": "77d93bce0f0ff76f1a52424f9c0aeb165990dc37a5e3aaf85031a2f6ab2967d1",
    "timestamp": 1438317621
  },
  "target": {
    "target_hash": "a64f10ca86a880115cc271232dc8577606dc6223cf009a4dd1290cd55b2d6a28",
    "target_uri ": "https://www.someurl.com/target/id",
    "target_proof": [
      {
        "parent": "ee32ac6eb702c289ba2a932e6562b2c45070121cacb26cabdee433a6cf2086cd",
        "left": "a64f10ca86a880115cc271232dc8577606dc6223cf009a4dd1290cd55b2d6a28",
        "right": "f07934733450ba14972b8fbea4c39ac05b0b8e2d8a45ddde9dbe03bb70942b6a"
      },
      {
        "parent": "8dbd52c5ff89b70711b06c143520ef4eb295c51040757c7a4ab56303f0f6b68f",
        "left": "ee32ac6eb702c289ba2a932e6562b2c45070121cacb26cabdee433a6cf2086cd",
        "right": "07084efda9cf5488ef9d4f9ad8bca8521581aaa32331b62aeb2fe3e132e62d1a"
      }
    ]
  },
  "extra": [
    {
      "custom_key_1": "value_1"
    },
    {
      "custom_key_2": "value_2"
    }
  ]
}

Verifying Chainpoint Proofs

Verification confirms that the proof is well formatted, and all proof operations lead to the expected anchor hash. Verification of current version 2.x proofs can be performed with the chainpoint-validate Javascript package for Node.js.