Verify a Chainpoint Proof Directly Using Bitcoin

node v8.17.0
version: 0.0.1
endpointsharetweet
Here are instructions for verifying a Chainpoint proof without needing a trusted third-party. Each Chainpoint proof contains a set of operations. To verify the proof, step through the operations and check if the resulting value matches the Merkle root of a Bitcoin block header. So long as you have a copy of the Bitcoin blockchain or access to a block explorer, you can verify a Chainpoint proof. We'll use this open-source library to parse and step through the operations of Chainpoint proof. It works offline. https://github.com/chainpoint/chainpoint-parse
Let's start by importing our single Javascript dependency.
// Parses, validates and calculates expected results for Chainpoint proofs // See : https://github.com/chainpoint/chainpoint-parse const cpp = require('chainpoint-parse')
Next, we'll use this sample Chainpoint proof that's anchored to the Bitcoin blockchain. This example is a Base64 encoded binary version of the Chainpoint proof. You can also use a JSON-LD formatted Chainpoint proof.
const proof = "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"
Use `chainpoint-parse` to read and calculate the Chainpoint proof's operations and return the expected Merkle root. All calculations are done locally and requires no external services. Click the grey triangle below to expand the code sample and view the JSON output of chainpoint-parse. The "btc_anchor_branch" has an "anchor_id" property of "503275". This represents the height of the Bitcoin block to which this proof is anchored. The "expected_value" is "c617f5faca34474bea7020d75c39cb8427a32145f9646586ecb9184002131ad9". This is the 'Merkle root' of block "503275".
// Parse a proof, calculating all of its proof operations // and displaying the final calculated values. const parsedProof = cpp.parse(proof) // pretty print it JSON.stringify(parsedProof, null, 2)
If you run a full Bitcoin Node, you can retrieve the Merkle root of block "503275" and see if it equals the expected value of "c617f5faca34474bea7020d75c39cb8427a32145f9646586ecb9184002131ad9”. You may also use a block explorer to look up the Merkle root of block "503275". For example, visit this URL click on the 'Advanced Details' button. https://live.blockcypher.com/btc/block/0000000000000000001d6f15f6f0e5de07b2225b03f2badfe21f73f208c7279e/ This displays the Merkle root of the block "503275". This matches the expected value of “c617f5faca34474bea7020d75c39cb8427a32145f9646586ecb9184002131ad9”, which confirms the Chainpoint proof is valid. It's also possible to use an API to retrieve the Merkle root. In the following example, we're calling Blockcypher's API and looking for the "mrkl_root" property:
// HTTP client and Async wrapper const request = require('request') const rp = require('request-promise') // A block explorer API URI you can retrieve BTC block data from, in this case for Block 503275 let uri = "https://api.blockcypher.com/v1/btc/main/blocks/503275?txstart=1&limit=1" // make the API request let block = await rp({ uri: uri, json: true })
If the Merkle root of the Bitcoin block matches the expected value calculated for your Chainpoint proof, then your proof is verified. In other words, this proves that the hash you submitted to generate this proof is represented in the Merkle root of a Bitcoin block. Congratulations!
Loading…

no comments

    sign in to comment