-
Notifications
You must be signed in to change notification settings - Fork 282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Node http endpoints and handlers #168
base: master
Are you sure you want to change the base?
Changes from 28 commits
ed1b563
8a9fe95
3fcd483
ad782fe
1d20d2a
b9b9396
0f98759
5db3f58
14a5c31
dc5e518
0722801
ffb2fc1
0fdce37
6baaa6d
b035103
721f8fd
593a151
5fd20d5
bccab33
32d8557
c0bec63
9050228
3b8a8a4
4dbf7f7
41f5088
d4015a5
4c6afb4
231e30e
177a78e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,8 @@ const Claim = require('../primitives/claim'); | |
const Address = require('../primitives/address'); | ||
const Network = require('../protocol/network'); | ||
const pkg = require('../pkg'); | ||
const rules = require('../covenants/rules'); | ||
const Resource = require('../dns/resource'); | ||
|
||
/** | ||
* HTTP | ||
|
@@ -432,6 +434,133 @@ class HTTP extends Server { | |
|
||
res.json(200, { success: true }); | ||
}); | ||
|
||
this.get('/name/:name', async (req, res) => { | ||
const valid = Validator.fromRequest(req); | ||
const name = valid.str('name'); | ||
|
||
if (!name || !rules.verifyName(name)) | ||
throw new Error('Invalid parameter.'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: |
||
|
||
const network = this.network; | ||
const height = this.chain.height; | ||
const nameHash = rules.hashName(name); | ||
const reserved = rules.isReserved(nameHash, height + 1, network); | ||
const [start, week] = rules.getRollout(nameHash, network); | ||
const ns = await this.chain.db.getNameState(nameHash); | ||
|
||
let info = null; | ||
|
||
if (ns) { | ||
if (!ns.isExpired(height, network)) | ||
info = ns.getJSON(height, network); | ||
} | ||
|
||
return res.json(200, { | ||
start: { | ||
reserved: reserved, | ||
week: week, | ||
start: start | ||
}, | ||
info | ||
}); | ||
}); | ||
|
||
this.get('/resource/hash/:hash', async (req, res) => { | ||
const valid = Validator.fromRequest(req); | ||
const hash = valid.bhash('hash'); | ||
|
||
if (!hash) | ||
throw new Error('Invalid hash.'); | ||
|
||
const ns = await this.chain.db.getNameState(hash); | ||
const height = this.chain.tip.height; | ||
const network = this.network; | ||
|
||
if (!ns) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also need to check if |
||
return res.json(404); | ||
|
||
return res.json(200, ns.getJSON(height,network)); | ||
}); | ||
|
||
this.get('/resource/name/:name', async (req, res) => { | ||
const valid = Validator.fromRequest(req); | ||
const name = valid.str('name'); | ||
|
||
if (!name || !rules.verifyName(name)) | ||
throw new Error('Invalid name.'); | ||
|
||
const nameHash = rules.hashName(name); | ||
const ns = await this.chain.db.getNameState(nameHash); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't want to return |
||
if (!ns || ns.data.length === 0) | ||
return null; | ||
|
||
const resource = Resource.decode(ns.data); | ||
|
||
return res.json(200, resource.getJSON(name)); | ||
}); | ||
|
||
this.get('/proof/name/:name', async (req, res) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that I think about it, there are different kinds of proofs. There is an Urkle Tree Proof, which authenticates the namestate and then there is a Merkle Proof for transactions in a block. Ideally we want to be able to support both of them and if we use |
||
const valid = Validator.fromRequest(req); | ||
const name = valid.str('name'); | ||
|
||
if (!name || !rules.verifyName(name)) | ||
throw new Error('Invalid name.'); | ||
|
||
const tip = this.chain.tip.hash; | ||
const height = this.chain.tip.height; | ||
const root = this.chain.tip.treeRoot; | ||
const nameHash = rules.hashName(name); | ||
const proof = await this.chain.db.prove(root, nameHash); | ||
|
||
return res.json(200, { | ||
hash: tip.toString('hex'), | ||
height: height, | ||
root: root.toString('hex'), | ||
name: name, | ||
key: nameHash.toString('hex'), | ||
proof: proof.toJSON() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The shape of
We should try to deduplicate any fields that correspond between the two. It feels a little bit cleaner to me to follow the style in other endpoints where the only object returned is a We want to be 100% sure that we can easily verify the proof client side. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤔 I dont entirely follow. This shape mirrors the response of the RPC method: Would you prefer something like: return {
hash: hash.toString('hex'),
height: height,
root: root.toString('hex'),
name: name,
key: key.toString('hex'),
...proof.toJSON() // <- This would achieve your de-duping.
}; It is definitely cleaner to return something.toJSON() - but to confirm, we have other handlers in this file that construct their response "in the handler" like: https://github.com/handshake-org/hsd/blob/master/lib/node/http.js#L354 Whichever we decide - Illl do the same for: https://github.com/handshake-org/hsd/pull/168/files/231e30eef2c442d4914c57cddd840a03624abac9#diff-bbe506ab5582252a30d6872d35fd8ce6R540 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Current question(s) I believe Im trying to answer: return res.json(200, primitive.toJSON()); // Like proof.toJSON? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This one was done that way because there was no There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Between a and b, I think something in between is good, it would be nice to have the height and the root along with the rest of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added the: return {
hash: hash.toString('hex'),
height: height,
root: root.toString('hex'),
name: name,
key: key.toString('hex'),
...proof.toJSON()
}; ☝️ This makes sense to me? Let me know if you feel otherwise! |
||
}); | ||
}); | ||
|
||
this.get('/proof/hash/:nameHash', async (req, res) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: |
||
const valid = Validator.fromRequest(req); | ||
const nameHash = valid.bhash('nameHash'); | ||
|
||
if (!nameHash) | ||
throw new Error('Invalid hash.'); | ||
|
||
const tip = this.chain.tip.hash; | ||
const height = this.chain.tip.height; | ||
const root = this.chain.tip.treeRoot; | ||
const proof = await this.chain.db.prove(root, nameHash); | ||
const ns = await this.chain.db.getNameState(nameHash); | ||
|
||
return res.json(200, { | ||
hash: tip.toString('hex'), | ||
height: height, | ||
root: root.toString('hex'), | ||
key: nameHash.toString('hex'), | ||
proof: proof.toJSON(), | ||
name: ns ? ns.name.toString() : null | ||
}); | ||
}); | ||
|
||
this.get('/grind', async (req, res) => { | ||
const valid = Validator.fromRequest(req); | ||
const size = valid.u32('size'); | ||
|
||
if (size < 1 || size > 63) | ||
throw new Error('Invalid length.'); | ||
|
||
const network = this.network; | ||
const height = this.chain.height; | ||
|
||
const name = await rules.grindName(size, height + 1, network); | ||
|
||
res.json(200, { name }); | ||
}); | ||
} | ||
|
||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each of these endpoints could use a comment describing their functionality