itns-sidechain/scripts/gen.js
2018-03-11 18:16:46 -07:00

341 lines
8.1 KiB
JavaScript

'use strict';
const fs = require('bfile');
const Path = require('path');
const consensus = require('../lib/protocol/consensus');
const Network = require('../lib/protocol/network');
const TX = require('../lib/primitives/tx');
const Block = require('../lib/primitives/block');
const Address = require('../lib/primitives/address');
const Witness = require('../lib/script/witness');
const Input = require('../lib/primitives/input');
const Output = require('../lib/primitives/output');
const util = require('../lib/utils/util');
const rules = require('../lib/covenants/rules');
const {HSKResource} = require('../lib/covenants/record');
const root = require('../etc/root.json');
const {EMPTY_ROOT} = require('../lib/trie/common');
const {types} = rules;
const networks = {
main: Network.get('main'),
testnet: Network.get('testnet'),
regtest: Network.get('regtest'),
simnet: Network.get('simnet')
};
const genesis = Address.fromHash(consensus.GENESIS_KEY, 0);
const investors = Address.fromHash(consensus.INVESTORS_KEY, 0);
const foundationHot = Address.fromHash(consensus.FOUNDATION_HOT, 0);
const foundation = Address.fromHash(consensus.FOUNDATION_KEY, 0);
const creators = Address.fromHash(consensus.CREATORS_KEY, 0);
const airdrop = Address.fromHash(consensus.AIRDROP_KEY, 0);
const names = Object.keys(root).sort();
function createGenesisBlock(options) {
let flags = options.flags;
let nonce = options.nonce;
if (!flags) {
flags = Buffer.from(
`01/Nov/2017 EFF to ICANN: Don't Pick Up the Censor's Pen`,
'ascii');
}
if (!nonce)
nonce = Buffer.alloc(consensus.NONCE_SIZE, 0x00);
const tx = new TX({
version: 0,
inputs: [{
prevout: {
hash: consensus.NULL_HASH,
index: 0xffffffff
},
witness: new Witness([flags]),
sequence: 0xffffffff
}],
outputs: [
{
value: consensus.GENESIS_REWARD,
address: genesis
},
{
value: consensus.MAX_INVESTORS,
address: investors
},
{
value: consensus.MAX_FOUNDATION,
address: foundation
},
{
value: consensus.MAX_CREATORS,
address: creators
},
{
value: consensus.MAX_AIRDROP,
address: airdrop
}
],
locktime: 0
});
const block = new Block({
version: 0,
prevBlock: consensus.NULL_HASH,
merkleRoot: tx.hash('hex'),
witnessRoot: tx.witnessHash('hex'),
trieRoot: EMPTY_ROOT.toString('hex'),
time: options.time,
bits: options.bits,
nonce: nonce,
solution: options.solution
});
block.txs.push(tx);
const claimer = new TX({
version: 0,
inputs: [{
prevout: {
hash: tx.hash('hex'),
index: 0
},
witness: new Witness(),
sequence: 0xffffffff
}],
outputs: [{
value: consensus.GENESIS_REWARD,
address: genesis
}],
locktime: 0
});
for (const name of names) {
const rawName = Buffer.from(name, 'ascii');
const claim = new Output();
claim.value = 0;
claim.address = foundationHot;
claim.covenant.type = types.CLAIM;
claim.covenant.items.push(rawName);
claimer.outputs.push(claim);
const dust = new Output();
dust.value = 0;
dust.address = foundationHot;
claimer.outputs.push(dust);
}
claimer.refresh();
const updater = new TX({
version: 0,
inputs: [],
outputs: [],
locktime: 0
});
let i = 1;
for (const name of names) {
const rawName = Buffer.from(name, 'ascii');
const res = HSKResource.fromJSON(root[name]);
const claimPrev = claimer.outpoint(i);
const dustPrev = claimer.outpoint(i + 1);
const claim = Input.fromOutpoint(claimPrev);
const dust = Input.fromOutpoint(dustPrev);
const update = new Output();
update.value = 0;
update.address = foundationHot;
update.covenant.type = types.REGISTER;
update.covenant.items.push(rawName);
update.covenant.items.push(res.toRaw());
update.covenant.items.push(consensus.ZERO_HASH);
const cold = new Output();
cold.value = 0;
cold.address = foundation;
cold.covenant.type = types.COLD;
cold.covenant.items.push(rawName);
updater.inputs.push(claim);
updater.inputs.push(dust);
updater.outputs.push(update);
updater.outputs.push(cold);
i += 2;
}
updater.refresh();
block.txs.push(claimer);
block.txs.push(updater);
block.merkleRoot = block.createMerkleRoot('hex');
block.witnessRoot = block.createWitnessRoot('hex');
return block;
}
const blocks = {
main: createGenesisBlock({
time: 1514765688,
bits: networks.main.pow.bits,
solution: new Uint32Array(networks.main.cuckoo.size)
}),
testnet: createGenesisBlock({
time: 1514765689,
bits: networks.testnet.pow.bits,
solution: new Uint32Array(networks.testnet.cuckoo.size)
}),
regtest: createGenesisBlock({
time: 1514765690,
bits: networks.regtest.pow.bits,
solution: new Uint32Array(networks.regtest.cuckoo.size)
}),
simnet: createGenesisBlock({
time: 1514765691,
bits: networks.simnet.pow.bits,
solution: new Uint32Array(networks.simnet.cuckoo.size)
})
};
function formatJS(name, block) {
const sol = block.solution.toArray();
let out = '';
out += `genesis.${name} = {\n`;
out += ` version: ${block.version},\n`;
out += ` hash: '${block.hash('hex')}',\n`;
out += ` prevBlock: '${block.prevBlock}',\n`;
out += ` merkleRoot:\n`;
out += ` '${block.merkleRoot}',\n`;
out += ` witnessRoot:\n`;
out += ` '${block.witnessRoot}',\n`;
out += ` trieRoot:\n`;
out += ` '${block.trieRoot}',\n`;
out += ` time: ${block.time},\n`;
out += ` bits: 0x${util.hex32(block.bits)},\n`;
out += ` nonce: Buffer.from('${block.nonce.toString('hex')}', 'hex'),\n`;
out += ` solution: new Uint32Array([\n`;
for (let i = 0; i < sol.length; i++)
out += ` 0x${util.hex32(sol[i])},\n`;
out = out.slice(0, -2) + '\n';
out += ` ]),\n`;
out += ` height: 0\n`;
out += `};`;
return out;
}
function formatData(name, block) {
const hex = block.toRaw().toString('base64');
const chunks = [`genesis.${name}Data = Buffer.from(\``];
for (let i = 0; i < hex.length; i += 50)
chunks.push(` ${hex.slice(i, i + 50)}`);
return chunks.join('\n') + '`, \'base64\');';
}
function formatC(name, block) {
const hdr = block.toHead().toString('hex');
const upper = name.toUpperCase();
const chunks = [`static const uint8_t HSK_GENESIS_${upper}[] = ""`];
for (let i = 0; i < hdr.length; i += 26)
chunks.push(` "${hdr.slice(i, i + 26)}"`);
const hex = chunks.join('\n');
const data = hex.replace(/([a-f0-9]{2})/g, '\\x$1');
return `${data};`;
}
const code = [
'// Autogenerated, do not edit.',
'',
`'use strict';`,
'',
`const data = require('./genesis-data.json');`,
'const genesis = exports;',
''
];
for (const name of Object.keys(blocks)) {
const upper = name[0].toUpperCase() + name.substring(1);
const block = blocks[name];
code.push('/*');
code.push(` * ${upper}`);
code.push(' */');
code.push('');
code.push(formatJS(name, block));
code.push('');
code.push(`genesis.${name}Data = Buffer.from(data.${name}, 'base64');`);
code.push('');
}
const json = JSON.stringify({
main: blocks.main.toRaw().toString('base64'),
testnet: blocks.testnet.toRaw().toString('base64'),
regtest: blocks.regtest.toRaw().toString('base64'),
simnet: blocks.simnet.toRaw().toString('base64')
}, null, 2);
const ccode = [
'#ifndef _HSK_GENESIS_H',
'#define _HSK_GENESIS_H',
''
];
for (const name of Object.keys(blocks)) {
const upper = name[0].toUpperCase() + name.substring(1);
const block = blocks[name];
ccode.push('/*');
ccode.push(` * ${upper}`);
ccode.push(' */');
ccode.push('');
ccode.push(formatC(name, block));
ccode.push('');
}
ccode.push('#endif');
ccode.push('');
const file = Path.resolve(
__dirname,
'..',
'lib',
'protocol',
'genesis.js'
);
fs.writeFileSync(file, code.join('\n'));
const jfile = Path.resolve(
__dirname,
'..',
'lib',
'protocol',
'genesis-data.json'
);
fs.writeFileSync(jfile, json);
const cfile = Path.resolve(
__dirname,
'..',
'etc',
'genesis.h'
);
fs.writeFileSync(cfile, ccode.join('\n'));