Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
covenants: Add 10k alexa to the soft-fork.
root are forever locked. top 10k, custom are locked for 4 years.
- Loading branch information
Showing
8 changed files
with
11,920 additions
and
28 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 |
---|---|---|
@@ -0,0 +1,116 @@ | ||
'use strict'; | ||
|
||
const assert = require('bsert'); | ||
const sha3 = require('bcrypto/lib/sha3'); | ||
const data = require('./lockup.json'); | ||
|
||
/* | ||
* Constants | ||
*/ | ||
|
||
const ZERO_HASH = sha3.zero.toString('hex'); | ||
|
||
/** | ||
* Locked up | ||
*/ | ||
|
||
class LockedUp { | ||
constructor(data) { | ||
const meta = data[ZERO_HASH]; | ||
|
||
this.data = data; | ||
this.size = meta[0]; | ||
} | ||
|
||
has(hash) { | ||
assert(Buffer.isBuffer(hash) && hash.length === 32); | ||
|
||
const hex = hash.toString('hex'); | ||
const item = this.data[hex]; | ||
|
||
if (!item) | ||
return false; | ||
|
||
return Array.isArray(item); | ||
} | ||
|
||
get(hash) { | ||
assert(Buffer.isBuffer(hash) && hash.length === 32); | ||
|
||
const hex = hash.toString('hex'); | ||
const item = this.data[hex]; | ||
|
||
if (!item || !Array.isArray(item)) | ||
return null; | ||
|
||
const target = item[0]; | ||
const flags = item[1]; | ||
const index = target.indexOf('.'); | ||
|
||
assert(index !== -1); | ||
|
||
const root = (flags & 1) !== 0; | ||
const custom = (flags & 2) !== 0; | ||
const name = target.substring(0, index); | ||
|
||
return { | ||
name, | ||
hash, | ||
target, | ||
root, | ||
custom | ||
}; | ||
} | ||
|
||
hasByName(name) { | ||
assert(typeof name === 'string'); | ||
|
||
if (name.length === 0 || name.length > 63) | ||
return false; | ||
|
||
return this.has(hashName(name)); | ||
} | ||
|
||
getByName(name) { | ||
assert(typeof name === 'string'); | ||
|
||
if (name.length === 0 || name.length > 63) | ||
return null; | ||
|
||
return this.get(hashName(name)); | ||
} | ||
|
||
*entries() { | ||
const keys = Object.keys(this.data); | ||
|
||
for (const key of keys) { | ||
const hash = Buffer.from(key, 'hex'); | ||
|
||
yield [hash, this.get(hash)]; | ||
} | ||
} | ||
|
||
*keys() { | ||
const keys = Object.keys(this.data); | ||
|
||
for (const key of keys) | ||
yield Buffer.from(key, 'hex'); | ||
} | ||
|
||
*values() { | ||
for (const [, item] of this.entries()) | ||
yield item; | ||
} | ||
|
||
[Symbol.iterator]() { | ||
return this.entries(); | ||
} | ||
} | ||
|
||
function hashName(name) { | ||
const raw = Buffer.from(name.toLowerCase(), 'ascii'); | ||
return sha3.digest(raw); | ||
} | ||
|
||
exports.LockedUp = LockedUp; | ||
exports.locked = new LockedUp(data); |
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,173 @@ | ||
'use strict'; | ||
|
||
const assert = require('bsert'); | ||
const Path = require('path'); | ||
const fs = require('bfile'); | ||
const sha3 = require('bcrypto/lib/sha3'); | ||
|
||
const FILE = Path.resolve(__dirname, 'lockup.db'); | ||
const DATA = fs.readFileSync(FILE); | ||
|
||
/** | ||
* Locked up | ||
*/ | ||
|
||
class LockedUp { | ||
constructor(data) { | ||
this.data = data; | ||
this.size = readU32(data, 0); | ||
} | ||
|
||
get prefixSize() { | ||
return 4; | ||
} | ||
|
||
_compare(b, off) { | ||
const a = this.data; | ||
|
||
for (let i = 0; i < 32; i++) { | ||
const x = a[off + i]; | ||
const y = b[i]; | ||
|
||
if (x < y) | ||
return -1; | ||
|
||
if (x > y) | ||
return 1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
_find(key) { | ||
let start = 0; | ||
let end = this.size - 1; | ||
|
||
while (start <= end) { | ||
const index = (start + end) >>> 1; | ||
const pos = this.prefixSize + index * 36; | ||
const cmp = this._compare(key, pos); | ||
|
||
if (cmp === 0) | ||
return readU32(this.data, pos + 32); | ||
|
||
if (cmp < 0) | ||
start = index + 1; | ||
else | ||
end = index - 1; | ||
} | ||
|
||
return -1; | ||
} | ||
|
||
_target(pos) { | ||
const len = this.data[pos]; | ||
return this.data.toString('ascii', pos + 1, pos + 1 + len); | ||
} | ||
|
||
_flags(pos) { | ||
const len = this.data[pos]; | ||
return this.data[pos + 1 + len]; | ||
} | ||
|
||
_index(pos) { | ||
const len = this.data[pos]; | ||
return this.data[pos + 1 + len + 1]; | ||
} | ||
|
||
_get(hash, pos) { | ||
const target = this._target(pos); | ||
const flags = this._flags(pos); | ||
const index = this._index(pos); | ||
const root = (flags & 1) !== 0; | ||
const custom = (flags & 2) !== 0; | ||
const name = target.substring(0, index); | ||
|
||
return { | ||
name, | ||
hash, | ||
target, | ||
root, | ||
custom | ||
}; | ||
} | ||
|
||
has(hash) { | ||
assert(Buffer.isBuffer(hash) && hash.length === 32); | ||
|
||
return this._find(hash) !== -1; | ||
} | ||
|
||
get(hash) { | ||
assert(Buffer.isBuffer(hash) && hash.length === 32); | ||
|
||
const pos = this._find(hash); | ||
|
||
if (pos === -1) | ||
return null; | ||
|
||
return this._get(hash, pos); | ||
} | ||
|
||
hasByName(name) { | ||
assert(typeof name === 'string'); | ||
|
||
if (name.length === 0 || name.length > 63) | ||
return false; | ||
|
||
return this.has(hashName(name)); | ||
} | ||
|
||
getByName(name) { | ||
assert(typeof name === 'string'); | ||
|
||
if (name.length === 0 || name.length > 63) | ||
return null; | ||
|
||
return this.get(hashName(name)); | ||
} | ||
|
||
*entries() { | ||
for (let i = 0; i < this.size; i++) { | ||
const pos = this.prefixSize + i * 36; | ||
const hash = this.data.slice(pos, pos + 32); | ||
const ptr = readU32(this.data, pos + 32); | ||
const item = this._get(hash, ptr); | ||
|
||
yield [hash, item]; | ||
} | ||
} | ||
|
||
*keys() { | ||
for (let i = 0; i < this.size; i++) { | ||
const pos = this.prefixSize + i * 36; | ||
|
||
yield this.data.slice(pos, pos + 32); | ||
} | ||
} | ||
|
||
*values() { | ||
for (const [, item] of this.entries()) | ||
yield item; | ||
} | ||
|
||
[Symbol.iterator]() { | ||
return this.entries(); | ||
} | ||
} | ||
|
||
/* | ||
* Helpers | ||
*/ | ||
|
||
function readU32(data, off) { | ||
return data.readUInt32LE(off); | ||
} | ||
|
||
function hashName(name) { | ||
const raw = Buffer.from(name.toLowerCase(), 'ascii'); | ||
return sha3.digest(raw); | ||
} | ||
|
||
exports.LockedUp = LockedUp; | ||
exports.locked = new LockedUp(DATA); |
Binary file not shown.
Oops, something went wrong.