199 lines
4.2 KiB
JavaScript
199 lines
4.2 KiB
JavaScript
/*!
|
|
* layout.js - blockchain data layout for bcoin
|
|
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
|
* https://github.com/bcoin-org/bcoin
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const assert = require('assert');
|
|
|
|
/*
|
|
* Database Layout:
|
|
* R -> tip hash
|
|
* O -> chain options
|
|
* e[hash] -> entry
|
|
* h[hash] -> height
|
|
* H[height] -> hash
|
|
* n[hash] -> next hash
|
|
* p[hash] -> tip index
|
|
* b[hash] -> block
|
|
* t[hash] -> extended tx
|
|
* c[hash] -> coins
|
|
* u[hash] -> undo coins
|
|
* v -> versionbits deployments
|
|
* v[bit][hash] -> versionbits state
|
|
* T[addr-hash][hash] -> dummy (tx by address)
|
|
* C[addr-hash][hash][index] -> dummy (coin by address)
|
|
* W+T[witaddr-hash][hash] -> dummy (tx by address)
|
|
* W+C[witaddr-hash][hash][index] -> dummy (coin by address)
|
|
*/
|
|
|
|
const layout = {
|
|
binary: true,
|
|
R: Buffer.from([0x52]),
|
|
O: Buffer.from([0x4f]),
|
|
V: Buffer.from([0x76]),
|
|
e: function e(hash) {
|
|
return pair(0x65, hash);
|
|
},
|
|
h: function h(hash) {
|
|
return pair(0x68, hash);
|
|
},
|
|
H: function H(height) {
|
|
return ipair(0x48, height);
|
|
},
|
|
n: function n(hash) {
|
|
return pair(0x6e, hash);
|
|
},
|
|
p: function p(hash) {
|
|
return pair(0x70, hash);
|
|
},
|
|
b: function b(hash) {
|
|
return pair(0x62, hash);
|
|
},
|
|
t: function t(hash) {
|
|
return pair(0x74, hash);
|
|
},
|
|
c: function c(hash, index) {
|
|
return bpair(0x63, hash, index);
|
|
},
|
|
u: function u(hash) {
|
|
return pair(0x75, hash);
|
|
},
|
|
v: function v(bit, hash) {
|
|
const key = Buffer.allocUnsafe(1 + 1 + 32);
|
|
assert(typeof bit === 'number');
|
|
key[0] = 0x76;
|
|
key[1] = bit;
|
|
write(key, hash, 2);
|
|
return key;
|
|
},
|
|
vv: function vv(key) {
|
|
assert(Buffer.isBuffer(key));
|
|
assert(key.length === 34);
|
|
return [key[1], key.toString('hex', 2, 34)];
|
|
},
|
|
T: function T(addr, hash) {
|
|
let len = addr.length;
|
|
|
|
if (typeof addr === 'string')
|
|
len /= 2;
|
|
|
|
let key;
|
|
if (len === 32) {
|
|
key = Buffer.allocUnsafe(65);
|
|
key[0] = 0xab; // W + T
|
|
write(key, addr, 1);
|
|
write(key, hash, 33);
|
|
} else if (len === 20) {
|
|
key = Buffer.allocUnsafe(53);
|
|
key[0] = 0x54; // T
|
|
write(key, addr, 1);
|
|
write(key, hash, 21);
|
|
} else {
|
|
assert(false);
|
|
}
|
|
|
|
return key;
|
|
},
|
|
C: function C(addr, hash, index) {
|
|
let len = addr.length;
|
|
|
|
assert(typeof index === 'number');
|
|
|
|
if (typeof addr === 'string')
|
|
len /= 2;
|
|
|
|
let key;
|
|
if (len === 32) {
|
|
key = Buffer.allocUnsafe(69);
|
|
key[0] = 0x9a; // W + C
|
|
write(key, addr, 1);
|
|
write(key, hash, 33);
|
|
key.writeUInt32BE(index, 65, true);
|
|
} else if (len === 20) {
|
|
key = Buffer.allocUnsafe(57);
|
|
key[0] = 0x43; // C
|
|
write(key, addr, 1);
|
|
write(key, hash, 21);
|
|
key.writeUInt32BE(index, 53, true);
|
|
} else {
|
|
assert(false);
|
|
}
|
|
|
|
return key;
|
|
},
|
|
pp: function pp(key) {
|
|
assert(Buffer.isBuffer(key));
|
|
assert(key.length === 33);
|
|
return key.toString('hex', 1, 33);
|
|
},
|
|
Cc: function Cc(key) {
|
|
assert(Buffer.isBuffer(key));
|
|
|
|
let hash, index;
|
|
if (key.length === 69) {
|
|
hash = key.toString('hex', 33, 65);
|
|
index = key.readUInt32BE(65, 0);
|
|
} else if (key.length === 57) {
|
|
hash = key.toString('hex', 21, 53);
|
|
index = key.readUInt32BE(53, 0);
|
|
} else {
|
|
assert(false);
|
|
}
|
|
|
|
return [hash, index];
|
|
},
|
|
Tt: function Tt(key) {
|
|
assert(Buffer.isBuffer(key));
|
|
|
|
if (key.length === 65)
|
|
return key.toString('hex', 33, 65);
|
|
|
|
assert(key.length === 53);
|
|
return key.toString('hex', 21, 53);
|
|
}
|
|
};
|
|
|
|
/*
|
|
* Helpers
|
|
*/
|
|
|
|
function write(data, str, off) {
|
|
if (Buffer.isBuffer(str))
|
|
return str.copy(data, off);
|
|
assert(typeof str === 'string');
|
|
return data.write(str, off, 'hex');
|
|
}
|
|
|
|
function pair(prefix, hash) {
|
|
const key = Buffer.allocUnsafe(33);
|
|
key[0] = prefix;
|
|
write(key, hash, 1);
|
|
return key;
|
|
}
|
|
|
|
function ipair(prefix, num) {
|
|
const key = Buffer.allocUnsafe(5);
|
|
assert(typeof num === 'number');
|
|
key[0] = prefix;
|
|
key.writeUInt32BE(num, 1, true);
|
|
return key;
|
|
}
|
|
|
|
function bpair(prefix, hash, index) {
|
|
const key = Buffer.allocUnsafe(37);
|
|
assert(typeof index === 'number');
|
|
key[0] = prefix;
|
|
write(key, hash, 1);
|
|
key.writeUInt32BE(index, 33, true);
|
|
return key;
|
|
}
|
|
|
|
/*
|
|
* Expose
|
|
*/
|
|
|
|
module.exports = layout;
|