Skip to content

Commit

Permalink
Merge pull request #8 from blockstack/feature/respond-for-pending
Browse files Browse the repository at this point in the history
Adds `/v1/names/` response for pending names
  • Loading branch information
kantai committed Mar 23, 2018
2 parents b033ec0 + 22a0fbb commit 20375ed
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 11 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
"description": "A subdomain registrar for Blockstack",
"main": "lib/index.js",
"dependencies": {
"bitcoinjs-lib": "^3.3.2",
"blockstack": "^0.16.0",
"cors": "^2.8.4",
"express": "^4.16.2",
"node-fetch": "^2.0.0",
"ripemd160": "^2.0.1",
"rwlock": "^5.0.0",
"sqlite3": "^3.1.13",
"winston": "^2.4.0",
Expand Down
2 changes: 1 addition & 1 deletion src/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ export class RegistrarQueueDB {
}

getStatusRecord(subdomainName) {
const lookup = 'SELECT status, status_more FROM subdomain_queue' +
const lookup = 'SELECT status, status_more, owner, zonefile FROM subdomain_queue' +
' WHERE subdomainName = ? ORDER BY queue_ix DESC LIMIT 1'
return dbAll(this.db, lookup, [subdomainName])
}
Expand Down
15 changes: 15 additions & 0 deletions src/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,21 @@ export function makeHTTPServer(config) {
})
})

app.get('/v1/names/:fullyQualified', (req, res) => {
server.getSubdomainInfo(req.params.fullyQualified)
.catch(error => {
logger.error(error)
return { message: { error: 'Error processing request' },
statusCode: 400 }
})
.then(infoResponse => {
res.writeHead(infoResponse.statusCode, HEADERS)
res.write(JSON.stringify(
infoResponse.message))
res.end()
})
})

const zonefileDelay = Math.min(2147483647,
Math.floor(60000 * config.checkTransactionPeriod))
const batchDelay = Math.min(2147483647,
Expand Down
2 changes: 1 addition & 1 deletion src/lookups.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import logger from 'winston'
export function isSubdomainRegistered(fullyQualifiedAddress: String) {
return new Promise((resolve, reject) => {
bskConfig.network.getNameInfo(fullyQualifiedAddress)
.then(() => resolve(true))
.then(nameInfo => resolve(nameInfo.status === 'registered_subdomain'))
.catch((err) => {
if (err.message === 'Name not found') {
resolve(false)
Expand Down
7 changes: 7 additions & 0 deletions src/operations.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { transactions, config as bskConfig, safety, hexStringToECPair } from 'bl
import { makeZoneFile } from 'zone-file'
import logger from 'winston'
import fetch from 'node-fetch'
import { crypto } from 'bitcoinjs-lib'
import RIPEMD160 from 'ripemd160'

export type SubdomainOp = {
owner: String,
Expand Down Expand Up @@ -130,6 +132,11 @@ Promise<Array<{txHash: String, status: Boolean}>> {
)
}

export function hash160(input: Buffer) {
const sha256 = crypto.sha256(input)
return (new RIPEMD160()).update(sha256).digest()
}

// this is a hack -- this is a stand-in while we roll out support for
// publishing zonefiles via core.blockstack
export function directlyPublishZonefile(zonefile: string) {
Expand Down
40 changes: 39 additions & 1 deletion src/server.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logger from 'winston'

import { makeUpdateZonefile, submitUpdate, checkTransactions } from './operations'
import { makeUpdateZonefile, submitUpdate, checkTransactions, hash160 } from './operations'
import { isRegistrationValid, isSubdomainRegistered, checkProofs } from './lookups'
import ReadWriteLock from 'rwlock'
import { RegistrarQueueDB } from './db'
Expand Down Expand Up @@ -278,6 +278,44 @@ export class SubdomainServer {
})
}
getSubdomainInfo(fullyQualifiedName: string) {
if (!fullyQualifiedName.endsWith(`.${this.domainName}`)) {
return Promise.resolve({
message: { error: 'Wrong domain' },
statusCode: 400 })
}
const namePieces = fullyQualifiedName.split('.')
if (namePieces.length !== 3) {
return Promise.resolve({
message: { error: 'Bad name' },
statusCode: 400 })
}
const subdomainName = namePieces[0]
return this.db.getStatusRecord(subdomainName)
.then((rows) => {
if (rows.length > 0) {
const statusRecord = rows[0]
const nameRecord = { blockchain: 'bitcoin' }
if (statusRecord.status === 'received') {
nameRecord.status = 'pending_subdomain'
nameRecord.last_txid = '' // eslint-disable-line camelcase
} else if (statusRecord.status === 'submitted') {
nameRecord.status = 'submitted_subdomain'
nameRecord.last_txid = statusRecord.status_more // eslint-disable-line camelcase
}
nameRecord.zonefile = statusRecord.zonefile
nameRecord.address = statusRecord.owner
nameRecord.zonefile_hash = hash160( // eslint-disable-line camelcase
Buffer.from(nameRecord.zonefile)).toString('hex')
return { message: nameRecord,
statusCode: 200 }
} else {
return { message: { error: 'No such subdomain' },
statusCode: 404 }
}
})
}
checkZonefiles() {
logger.debug('Checking for outstanding transactions.')
return new Promise((resolve, reject) => {
Expand Down
4 changes: 2 additions & 2 deletions tests/src/unitTestLookups.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function unitTestLookups() {

nock('https://core.blockstack.org')
.get('/v1/names/foo.bar.id')
.reply(200, {})
.reply(200, { status: 'registered_subdomain'})

isSubdomainRegistered('foo.bar.id')
.then(x => t.ok(x))
Expand Down Expand Up @@ -66,7 +66,7 @@ export function unitTestLookups() {
nock.cleanAll()
nock('https://core.blockstack.org')
.get('/v1/names/foo.bar.id')
.reply(200, {})
.reply(200, { status: 'registered_subdomain'})

nock('https://core.blockstack.org')
.get('/v1/names/bar.bar.id')
Expand Down
25 changes: 19 additions & 6 deletions tests/src/unitTestServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ const testSK = 'c14b3044ca7f31fc68d8fcced6b60effd350c280e7aa5c4384c6ef32c0cb129f
export function testSubdomainServer() {

test('queueRegistration', (t) => {
t.plan(10)
t.plan(14)
nock.cleanAll()

nock('https://core.blockstack.org')
.persist()
.get('/v1/names/foo.bar.id')
.reply(200, {})
.reply(200, { status: 'registered_subdomain'})

nock('https://core.blockstack.org')
.persist()
Expand Down Expand Up @@ -81,7 +81,7 @@ export function testSubdomainServer() {
() =>
s.getSubdomainStatus('bar')
.then((x) =>
t.ok(x.status.startsWith('Subdomain is queued for update', 'bar.bar.id should be queued'))))
t.ok(x.status.startsWith('Subdomain is queued for update'), 'bar.bar.id should be queued')))
.then(
() =>
s.updateQueueStatus(['bar'], 'txhash'))
Expand All @@ -101,8 +101,21 @@ export function testSubdomainServer() {
s.getSubdomainStatus('tar')
.then((x) =>
t.ok(x.status.startsWith('Subdomain not registered', 'tar.bar.id should not be queued'))))

})
.then(
() =>
s.getSubdomainInfo('bar.bar.id')
.then(resp =>
{
t.equal(resp.message.status, 'submitted_subdomain')
t.equal(resp.message.address, testAddress)
t.equal(resp.message.last_txid, 'txhash')
}))
.then(
() =>
s.getSubdomainInfo('tar.bar.id')
.then(resp => t.equal(resp.statusCode, 404)))
.catch( (err) => { console.log(err.stack) } )
})

test('apiKeyOnly', (t) => {
t.plan(2)
Expand Down Expand Up @@ -207,7 +220,7 @@ export function testSubdomainServer() {
nock('https://core.blockstack.org')
.get('/v1/names/foo.bar.id')
.times(1)
.reply(200, {})
.reply(200, { status: 'registered_subdomain'})
})
.then(() => s.lock.writeLock((release) => {
s.submitBatch()
Expand Down

0 comments on commit 20375ed

Please sign in to comment.