This repository has been archived by the owner on Dec 6, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
199 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
'use strict' | ||
|
||
exports.resolver = require('./resolver.js') | ||
exports.util = require('./util.js') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
'use strict' | ||
|
||
const util = require('./util') | ||
|
||
const resolve = (binaryBlob, path, callback) => { | ||
if (typeof path === 'function') { | ||
callback = path | ||
path = undefined | ||
} | ||
|
||
util.deserialize(binaryBlob, (err, dagNode) => { | ||
if (err) { | ||
return callback(err) | ||
} | ||
|
||
// Requesting the root node returns the deserialized block | ||
if (!path || path === '/') { | ||
return callback(null, { | ||
value: dagNode, | ||
remainderPath: '' | ||
}) | ||
} | ||
|
||
const pathArray = path.split('/') | ||
// `/` is the first element | ||
pathArray.shift() | ||
|
||
// The values that can directly be resolved | ||
let value | ||
// Links to other blocks | ||
let link | ||
switch (pathArray[0]) { | ||
case 'version': | ||
value = dagNode.version | ||
break | ||
case 'timestamp': | ||
value = dagNode.timestamp | ||
break | ||
case 'difficulty': | ||
value = dagNode.bits | ||
break | ||
case 'nonce': | ||
value = dagNode.nonce | ||
break | ||
case 'parent': | ||
link = dagNode.prevHash | ||
break | ||
case 'tx': | ||
link = dagNode.merkleRoot | ||
break | ||
default: | ||
return callback(new Error('No such path'), null) | ||
} | ||
|
||
let remainderPath = pathArray.slice(1).join('/') | ||
// Bitcoin has only top-level fields, every deeper nesting needs to | ||
// be a link | ||
if (value !== undefined) { | ||
if (remainderPath.length > 0) { | ||
return callback(new Error('No such path'), null) | ||
} else { | ||
return callback(null, { | ||
value: value, | ||
remainderPath: '' | ||
}) | ||
} | ||
} else { | ||
// It's a link | ||
return callback(null, { | ||
value: {'/': util.hashToCid(link)}, | ||
remainderPath: remainderPath | ||
}) | ||
} | ||
}) | ||
} | ||
|
||
module.exports = { | ||
resolve: resolve | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/* eslint-env mocha */ | ||
'use strict' | ||
|
||
const loadFixture = require('aegir/fixtures') | ||
const chai = require('chai') | ||
const dirtyChai = require('dirty-chai') | ||
const expect = chai.expect | ||
chai.use(dirtyChai) | ||
const CID = require('cids') | ||
const IpldBitcoin = require('../src/index') | ||
|
||
const fixtureBlockHex = loadFixture(__dirname, 'fixtures/block.hex') | ||
const fixtureBlock = Buffer.from(fixtureBlockHex.toString(), 'hex') | ||
|
||
describe('IPLD format resolver API resolve()', () => { | ||
it('should return the deserialized node if no path is given', (done) => { | ||
IpldBitcoin.resolver.resolve(fixtureBlock, (err, value) => { | ||
expect(err).to.not.exist() | ||
expect(value.remainderPath).is.empty() | ||
expect(value.value).is.not.empty() | ||
done() | ||
}) | ||
}) | ||
|
||
it('should return the deserialized node if the root is requested', (done) => { | ||
IpldBitcoin.resolver.resolve(fixtureBlock, '/', (err, value) => { | ||
expect(err).to.not.exist() | ||
expect(value.remainderPath).is.empty() | ||
expect(value.value).is.not.empty() | ||
done() | ||
}) | ||
}) | ||
|
||
it('should return the version', (done) => { | ||
verifyPath(fixtureBlock, '/version', 2, done) | ||
}) | ||
|
||
it('should return the timestamp', (done) => { | ||
verifyPath(fixtureBlock, '/timestamp', 1386981279, done) | ||
}) | ||
|
||
it('should return the difficulty', (done) => { | ||
verifyPath(fixtureBlock, '/difficulty', 419740270, done) | ||
}) | ||
|
||
it('should return the nonce', (done) => { | ||
verifyPath(fixtureBlock, '/nonce', 3159344128, done) | ||
}) | ||
|
||
it('should error on non-existent path', (done) => { | ||
verifyError(fixtureBlock, '/something/random', done) | ||
}) | ||
|
||
it('should error on partially matching path that isn\'t a link', (done) => { | ||
verifyError(fixtureBlock, '/version/but/additional/things', done) | ||
}) | ||
|
||
it('should return a link when parent is requested', (done) => { | ||
IpldBitcoin.resolver.resolve(fixtureBlock, '/parent', (err, value) => { | ||
expect(err).to.not.exist() | ||
expect(value.remainderPath).is.empty() | ||
expect(value.value).to.deep.equal({ | ||
'/': new CID('z4HFzdHLxSgJvCMJrsDtV7MgqiGALZdbbxgcTLVUUXQGBkGYjLb')}) | ||
done() | ||
}) | ||
}) | ||
|
||
it('should return a link and remaining path when parent is requested', | ||
(done) => { | ||
IpldBitcoin.resolver.resolve(fixtureBlock, '/parent/timestamp', | ||
(err, value) => { | ||
expect(err).to.not.exist() | ||
expect(value.remainderPath).to.equal('timestamp') | ||
expect(value.value).to.deep.equal({ | ||
'/': | ||
new CID('z4HFzdHLxSgJvCMJrsDtV7MgqiGALZdbbxgcTLVUUXQGBkGYjLb')}) | ||
done() | ||
}) | ||
}) | ||
|
||
it('should return a link when transactions are requested', (done) => { | ||
IpldBitcoin.resolver.resolve(fixtureBlock, '/tx/some/remainder', | ||
(err, value) => { | ||
expect(err).to.not.exist() | ||
expect(value.remainderPath).to.equal('some/remainder') | ||
expect(value.value).to.deep.equal({ | ||
'/': new CID('z4HFzdHD15kVvtmVzeD7z9sisZ7acSC88wXS3KJGwGrnr2DwcVQ')}) | ||
done() | ||
}) | ||
}) | ||
}) | ||
|
||
const verifyPath = (block, path, expected, done) => { | ||
IpldBitcoin.resolver.resolve(block, path, (err, value) => { | ||
expect(err).to.not.exist() | ||
expect(value.remainderPath).is.empty() | ||
expect(value.value).is.equal(expected) | ||
done() | ||
}) | ||
} | ||
|
||
const verifyError = (block, path, done) => { | ||
IpldBitcoin.resolver.resolve(block, path, (err, value) => { | ||
expect(value).to.not.exist() | ||
expect(err).to.be.an('error') | ||
done() | ||
}) | ||
} |