Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Options:
-s, --server specify server to use[string] [default: "http://0.0.0.0"]
-q, --quiet suppress all non-error output [boolean]
-j, --json format all output as json [boolean]
-b, --btc display btc specific information where applicable [boolean]
-b, --btc run btc specific operations where applicable [boolean]
--help show help [boolean]

You must specify a command.
Expand Down Expand Up @@ -137,6 +137,19 @@ chp verify 52eb62c0-f556-11e7-bcf8-016fed1c55ad

You can see here that the proof represented by the `node_hash_id` provided is anchored to the Calendar (`cal`) level.

#### SPV Verification

If you have a bitcoin node running that you would like to verify proofs against, pass the `--btc`
or `-b` flag. Since only the block headers are required to verify a proof, an spv node should be
sufficient to verify. Only the [bcoin](https://bcoin.io) API is currently supported, though this
could be expanded in the future.

To make your target node's information available to the verification client, add a `bcoin.conf`
file in your `~/.chainpoint` directory with all relevant information (`host`, `port`, `api-key`, etc)
See [here](http://bcoin.io/api-docs/index.html#configuring-clients) for more information.
Environment variables (prefaced with `BCOIN_`) and command line args (prefaced with `--bcoin-`)
are also supported configuration options.

### Viewing a Proof

You can of course view a proof in its entirety by asking
Expand Down Expand Up @@ -206,14 +219,13 @@ You can see in this case I piped the output of the `show` sub-command to the `jq
### Evaluating a proof

`evaluate <hash_id>` calculates and displays the expected values for each anchor in the proof.
Adding `--btc` or `-b` will return the previous outpoint hash for the first input of the evaluated bitcoin proofs.
This can be useful for evaluating proofs with light clients.
Adding `--btc` or `-b` will return the txid of the anchor transaction.

```
chp evaluate b640f9f0-3661-11e9-9c57-018b108544a2

b640f9f0-3661-11e9-9c57-018b108544a2 | cal | 2755298 | ab1dc08a1950ade9d4d603c90d655307eb765905148f6e18eddeb64ca241b7b4
b640f9f0-3661-11e9-9c57-018b108544a2 | btc | 564116 | af81bc00748ed3beab4f08ad16b33bb88aefdc0a283eb4446cf8d83b38ea7133 | 1 | 6a630dbd22cf54f2da91396e48f025cf1f154ffa8eb7d9642b969da39921d6ea
b640f9f0-3661-11e9-9c57-018b108544a2 | btc | 564116 | af81bc00748ed3beab4f08ad16b33bb88aefdc0a283eb4446cf8d83b38ea7133 | 7cdcefb56c2ec3230b2edb2ff5d1adf4a8acf4525850e1f0248b803cfe96dd02

```

Expand Down
7 changes: 7 additions & 0 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,13 @@ async function startAsync() {
requiresArg: false,
description: 'process all items in local database',
type: 'boolean'
})
.option('b', {
alias: 'btc',
demandOption: false,
requiresArg: false,
description: 'verify against a bitcoin spv node',
type: 'boolean'
}).argv
verifyCmd.executeAsync(yargs, argv)
})
Expand Down
5 changes: 1 addition & 4 deletions lib/evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,7 @@ function displayOutputResults(resultsArray, outputObj, quiet, json, btc) {
}
if (btc && result.raw_btc_tx) {
tx = TX.fromRaw(result.raw_btc_tx, 'hex')
// 1 prevout should be sufficient to verify anchor
// but show the count to provide additional information
output.prevout_count = tx.inputs.length
output.prevout_1 = tx.inputs[0].prevout.rhash()
output.txid = tx.txid()
}
outputObj.addSuccessResult(output)
}
Expand Down
115 changes: 63 additions & 52 deletions lib/verify.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ async function executeAsync(yargs, argv) {
// honor the json directive if set
let json = argv.json || false

let btc = argv.btc || false

let verifyAll = argv.all
if (!verifyAll) {
// check for valid argument value
Expand Down Expand Up @@ -68,12 +70,15 @@ async function executeAsync(yargs, argv) {

let verifyResults
try {
verifyResults = await VerifyProofs([
{
proof: hashItem.proof,
nodeUri: targetNodeUri
}
])
verifyResults = await VerifyProofs(
[
{
proof: hashItem.proof,
nodeUri: targetNodeUri
}
],
btc
)
} catch (error) {
console.error(`ERROR : Could not verify proof`)
return
Expand Down Expand Up @@ -135,7 +140,7 @@ async function executeAsync(yargs, argv) {

let verifyResults
try {
verifyResults = await VerifyProofs(proofData)
verifyResults = await VerifyProofs(proofData, btc)
} catch (error) {
console.error(`ERROR : Could not verify proofs`)
return
Expand Down Expand Up @@ -172,58 +177,64 @@ function displayOutputResults(resultsArray, outputObj, quiet, json) {
outputObj.display(quiet, json)
}

async function VerifyProofs(proofData) {
async function VerifyProofs(proofData, btc) {
let verifyResponse

try {
// Create a lookup table of proofs grouped by their common nodeURI
// These groups will be verified in separate calls because the chp.verifyProofs
// command accepts one URI for a group of proofs.
let proofDataURIGroups = proofData.reduce((results, proofDataItem) => {
if (results[proofDataItem.nodeUri] === undefined) {
results[proofDataItem.nodeUri] = [proofDataItem.proof]
} else {
results[proofDataItem.nodeUri].push(proofDataItem.proof)
if (btc) {
let proofs = proofData.map(item => item.proof)
verifyResponse = await chp.spvVerifyProofs(proofs)
} else {
// Create a lookup table of proofs grouped by their common nodeURI
// These groups will be verified in separate calls because the chp.verifyProofs
// command accepts one URI for a group of proofs.
let proofDataURIGroups = proofData.reduce((results, proofDataItem) => {
if (results[proofDataItem.nodeUri] === undefined) {
results[proofDataItem.nodeUri] = [proofDataItem.proof]
} else {
results[proofDataItem.nodeUri].push(proofDataItem.proof)
}
return results
}, {})

// define a function for verifying a set of proofs sharing a common nodeUri
let verifySetAsync = async proofDataSet => {
let firstAttempt = true
return retry(
async () => {
let targetURI = firstAttempt ? proofDataSet.nodeUri : null
firstAttempt = false
return chp.verifyProofs(proofDataSet.proofs, targetURI)
},
{
retries: 5, // The maximum amount of times to retry the operation. Default is 10
factor: 1, // The exponential factor to use. Default is 2
minTimeout: 10, // The number of milliseconds before starting the first retry. Default is 1000
maxTimeout: 10
}
)
}
return results
}, {})

// define a function for verifying a set of proofs sharing a common nodeUri
let verifySetAsync = async proofDataSet => {
let firstAttempt = true
return retry(
async () => {
let targetURI = firstAttempt ? proofDataSet.nodeUri : null
firstAttempt = false
return chp.verifyProofs(proofDataSet.proofs, targetURI)
},
{
retries: 5, // The maximum amount of times to retry the operation. Default is 10
factor: 1, // The exponential factor to use. Default is 2
minTimeout: 10, // The number of milliseconds before starting the first retry. Default is 1000
maxTimeout: 10
// create a verify task for each set of proofs with a unique nodeUri
let verifyTasks = []
for (var nodeUri in proofDataURIGroups) {
if (proofDataURIGroups.hasOwnProperty(nodeUri)) {
let task = verifySetAsync({
proofs: proofDataURIGroups[nodeUri],
nodeUri: nodeUri
})
verifyTasks.push(task)
}
)
}

// create a verify task for each set of proofs with a unique nodeUri
let verifyTasks = []
for (var nodeUri in proofDataURIGroups) {
if (proofDataURIGroups.hasOwnProperty(nodeUri)) {
let task = verifySetAsync({
proofs: proofDataURIGroups[nodeUri],
nodeUri: nodeUri
})
verifyTasks.push(task)
}
}

// execute and await thew results of all verify tasks
let verifyTasksResults = await Promise.all(verifyTasks)
// combine all veridy results into a single verify results array
verifyResponse = verifyTasksResults.reduce((results, response) => {
results.push(...response)
return results
}, [])
// execute and await the results of all verify tasks
let verifyTasksResults = await Promise.all(verifyTasks)
// combine all verify results into a single verify results array
verifyResponse = verifyTasksResults.reduce((results, response) => {
results.push(...response)
return results
}, [])
}
} catch (error) {
console.error(`Could not verify proofs : ${error.message}`)
}
Expand Down
Loading