-
Notifications
You must be signed in to change notification settings - Fork 92
/
genesis.js
171 lines (127 loc) · 5.65 KB
/
genesis.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
var $ = require("./utils");
var Hash = require('multi-hashing');
var defaults = {
//the (unix) time when the genesisblock is created
time: Math.round((new Date()).getTime() / 1000),
//the pszTimestamp found in the coinbase of the genesisblock
timestamp: "Don't work for weekends, work for our goals.",
//the first value of the nonce that will be incremented when searching the genesis hash
nonce: 1,
//the PoW algorithm: [x11|x13|x15|geek|quark|keccak|qubit|neoscrypt|lyra2re...]
algorithm: 'geek',
//the pubkey found in the output script
pubkey: '04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f',
//the value in coins for the output, full value (exp. in bitcoin 5000000000 - To get other coins value: Block Value * 100000000)
value: 5000000000,
//the target in compact representation, associated to a difficulty of 1
bits: 0x1e0ffff0,
locktime: 0
}
require('yargs')
.alias('t', 'time')
.alias('z', 'timestamp')
.alias('n', 'nonce')
.alias('a', 'algorithm')
.alias('p', 'pubkey')
.alias('v', 'value')
.alias('b', 'bits')
.alias('l', 'locktime')
.alias('h', 'help')
.help()
.command('*', 'create genesis block', () => { }, (argv) => {
// console.log(argv);
var options = Object.assign({}, defaults, argv);
// console.log(options);
var merkle_root = $.sha256d(createTx(options));
var genesisblock = createBlock(merkle_root, options);
console.log("---------------");
console.log("algorithm: %s", options.algorithm);
console.log("pzTimestamp: %s", options.timestamp);
console.log("pubkey: %s", options.pubkey);
console.log("bits: %s", options.bits);
console.log("time: %s", options.time);
console.log("merkle root hash: %s", $.reverseBuffer(merkle_root).toString('hex'));
PoW(genesisblock, options);
//console.log("genesis block: %s", genesisblock.toString('hex'));
// console.log($.reverseBuffer(hash_merkle_root).toString('hex'));
})
.argv;
function createInputScript(options) {
var tz = options.timestamp;
var psz_prefix = tz.length > 76 ? '4c' : '';
var script_prefix = '04ffff001d0104' + psz_prefix + Buffer.from(String.fromCharCode(tz.length)).toString('hex');
return Buffer.from(script_prefix + Buffer.from(tz).toString('hex'), 'hex');
}
function createOutputScript(options) {
return Buffer.from('41' + options.pubkey + 'ac', 'hex');
}
function createTx(options) {
var input = createInputScript(options);
var out = createOutputScript(options);
var size = 4 // tx version
+ 1 // number of inputs
+ 32 // hash of previous output
+ 4 // previous output's index
+ 1 // 1 byte for the size of scriptSig
+ input.length
+ 4 // size of sequence
+ 1 // number of outputs
+ 8 // 8 bytes for coin value
+ 1 // 1 byte to represent size of the pubkey Script
+ out.length
+ 4; // 4 bytes for lock time
var tx = Buffer.alloc(size);
var position = 0;
tx.writeInt32LE(1, position);
tx.writeInt32LE(1, position += 4);
tx.write(Buffer.alloc(32).toString('hex'), position += 1, 32, 'hex');
//tx.writeInt32LE(0xFFFFFFFF, position += 32, 4);
tx.writeDoubleLE(0xFFFFFFFF, position += 32, 4);
tx.writeInt32LE(input.length, position += 4);
tx.write(input.toString('hex'), position += 1, input.length, "hex");
//tx.writeInt32LE(0xFFFFFFFF, position += input.length, 4);
tx.writeDoubleLE(0xFFFFFFFF, position += input.length);
tx.writeInt32LE(1, position += 4);
tx.write(Buffer.from($.numToBytes(options.value)).toString('hex'), position += 1, 8, 'hex'); // 50 * coin
tx.writeInt32LE(0x43, position += 8);
//tx.write(input.toString('hex'), position += 1, input.length, "hex");
tx.write(out.toString('hex'), position += 1, out.length, "hex");
tx.writeInt32LE(options.locktime, position += out.length);
// console.log(tx.toString('hex'));
return tx;
};
function createBlock(merkleRoot, options) {
var block = Buffer.alloc(80);
var position = 0;
block.writeInt32LE(1, position); //version
block.write(Buffer.alloc(32).toString('hex'), position += 4, 32, 'hex'); //previousblockhash
block.write(merkleRoot.toString('hex'), position += 32, 32, 'hex');
block.writeInt32LE(options.time, position += 32);
//block.write(Buffer.from($.numToBytes(options.time)).toString('hex'), position += 32, 4, 'hex');
block.writeInt32LE(options.bits, position += 4);
//block.write(Buffer.from($.numToBytes(options.bits)).toString('hex'), position += 4, 4, 'hex');
block.writeInt32LE(options.nonce, position += 4);
return block;
};
function PoW(data, options) {
console.log('Searching for genesis hash...');
var nonce = options.nonce;
//var target = $.numToBytes((options.bits & 0xffffff) * 2 ** (8 * ((options.bits >> 24) - 3)));
// console.log('' + target.toString('hex'));
while (true) {
var hash = $.reverseBuffer(Hash[options.algorithm](data)).toString('hex');
// var hash2 = $.reverseBuffer(hash).toString('hex');
// var val = parseInt(hash2, 16);
if (hash.match(/^00000/)) {
console.log("nonce: %s", nonce);
console.log("genesis hash: %s", hash);
return;
} else {
nonce += 1;
// if (nonce % 2000 == 0) {
// console.log("nonce: %s | hash: %s ", nonce, hash.toString('hex'));
// }
data.writeInt32LE(nonce, data.length - 4);
}
}
}