From f62ceb851580ad7eb3335417d419a0f800803cb8 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 30 Mar 2016 19:10:59 -0700 Subject: [PATCH] segnet4 --- lib/bcoin/chain.js | 130 +++++++++++++++++++++----------- lib/bcoin/chainblock.js | 8 +- lib/bcoin/fullnode.js | 2 +- lib/bcoin/protocol/constants.js | 10 +-- lib/bcoin/protocol/network.js | 126 +++++++++++++++++++++---------- lib/bcoin/spvnode.js | 2 +- lib/bcoin/walletdb.js | 2 +- scripts/gen.js | 67 ++++++++++------ 8 files changed, 232 insertions(+), 115 deletions(-) diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 861633b3..523e5298 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -502,52 +502,73 @@ Chain.prototype._verify = function _verify(block, prev, callback) { // if (block.version >= 8 && prev.isUpgraded(8)) // lockFlags |= constants.flags.MEDIAN_TIME_PAST; - // Can't verify any further when merkleblock or headers. - if (block.type !== 'block') - return done(null, flags); + if (network.type === 'segnet4') { + self.getState(prev, null, 'witness', function(err, state) { + if (err) + return callback(err); - // Make sure the height contained in the coinbase is correct. - if (coinbaseHeight) { - if (block.getCoinbaseHeight() !== height) - return done(new VerifyError(block, 'invalid', 'bad-cb-height', 100)); - } + if (state === constants.thresholdStates.ACTIVE) { + flags |= constants.flags.VERIFY_WITNESS; + segwit = true; + self.segwitActive = true; + } else { + self.segwitActive = false; + } - if (block.version >= 5 && segwit) { - if (block.commitmentHash !== block.getCommitmentHash()) { - return done(new VerifyError(block, - 'invalid', - 'bad-blk-wit-length', - 100)); - } + return finish(); + }); } else { - if (block.hasWitness()) { - return done(new VerifyError(block, - 'invalid', - 'unexpected-witness', - 100)); - } + finish(); } - // Get timestamp for tx.isFinal(). - ts = (lockFlags & constants.flags.MEDIAN_TIME_PAST) - ? medianTime - : block.ts; + function finish() { + // Can't verify any further when merkleblock or headers. + if (block.type !== 'block') + return done(null, flags); - // Check all transactions - for (i = 0; i < block.txs.length; i++) { - tx = block.txs[i]; - - // Transactions must be finalized with - // regards to nSequence and nLockTime. - if (!tx.isFinal(height, ts)) { - return done(new VerifyError(block, - 'invalid', - 'bad-txns-nonfinal', - 10)); + // Make sure the height contained in the coinbase is correct. + if (coinbaseHeight) { + if (block.getCoinbaseHeight() !== height) + return done(new VerifyError(block, 'invalid', 'bad-cb-height', 100)); } - } - return done(null, flags); + if (block.version >= 5 && segwit) { + if (block.commitmentHash !== block.getCommitmentHash()) { + return done(new VerifyError(block, + 'invalid', + 'bad-blk-wit-length', + 100)); + } + } else { + if (block.hasWitness()) { + return done(new VerifyError(block, + 'invalid', + 'unexpected-witness', + 100)); + } + } + + // Get timestamp for tx.isFinal(). + ts = (lockFlags & constants.flags.MEDIAN_TIME_PAST) + ? medianTime + : block.ts; + + // Check all transactions + for (i = 0; i < block.txs.length; i++) { + tx = block.txs[i]; + + // Transactions must be finalized with + // regards to nSequence and nLockTime. + if (!tx.isFinal(height, ts)) { + return done(new VerifyError(block, + 'invalid', + 'bad-txns-nonfinal', + 10)); + } + } + + return done(null, flags); + } }); }; @@ -1770,7 +1791,7 @@ Chain.prototype.getState = function getState(prev, block, id, callback) { timeTimeout = deployment.timeout; compute = []; - if (block && block.isGenesis()) + if (!prev) return callback(null, constants.thresholdStates.DEFINED); if (((prev.height + 1) % period) !== 0) { @@ -1778,9 +1799,11 @@ Chain.prototype.getState = function getState(prev, block, id, callback) { return prev.getAncestorByHeight(height, function(err, ancestor) { if (err) return callback(err); - if (!ancestor) - return callback(null, constants.thresholdStates.DEFINED); - return self.getState(ancestor, block, callback); + if (ancestor) { + assert(ancestor.height === height); + assert(((ancestor.height + 1) % period) === 0); + } + return self.getState(ancestor, block, id, callback); }); } @@ -1918,6 +1941,24 @@ Chain.prototype.isSegwitActive = function isSegwitActive(callback) { var tip = this.tip; var unlock; + if (!network.witness) { + this.segwitActive = false; + return utils.asyncify(callback)(null, false); + } + + if (network.type === 'segnet4') { + return this.tip.getPrevious(function(err, prev) { + if (err) + return callback(err); + + return self.getState(prev, null, 'witness', function(err, state) { + if (err) + return callback(err); + return callback(null, state === constants.thresholdStates.ACTIVE); + }); + }); + } + if (this.segwitActive != null) return utils.asyncify(callback)(null, this.segwitActive); @@ -1933,6 +1974,11 @@ Chain.prototype.isSegwitActive = function isSegwitActive(callback) { callback = utils.wrap(callback, unlock); + if (tip.ancestors.length) { + self.segwitActive = tip.isUpgraded(5); + return callback(null, self.segwitActive); + } + tip.ensureAncestors(function(err) { if (err) return callback(err); diff --git a/lib/bcoin/chainblock.js b/lib/bcoin/chainblock.js index e44aa390..9f15d933 100644 --- a/lib/bcoin/chainblock.js +++ b/lib/bcoin/chainblock.js @@ -143,8 +143,12 @@ ChainBlock.prototype.isMainChain = function isMainChain(callback) { }; ChainBlock.prototype.getAncestorByHeight = function getAncestorByHeight(height, callback) { + if (height < 0) + return utils.nextTick(callback); + assert(height >= 0); assert(height <= this.height); + return this.getAncestor(this.height - height, function(err, entry) { if (err) return callback(err); @@ -164,10 +168,10 @@ ChainBlock.prototype.getAncestor = function getAncestor(index, callback) { if (err) return callback(err); - if (ancestors.length !== index + 1) + if (ancestors.length < index + 1) return callback(); - return callback(null, ancestors[ancestors.length - 1]); + return callback(null, ancestors[index]); }); }; diff --git a/lib/bcoin/fullnode.js b/lib/bcoin/fullnode.js index b9fdeaa0..bf0fc7ac 100644 --- a/lib/bcoin/fullnode.js +++ b/lib/bcoin/fullnode.js @@ -54,7 +54,7 @@ Fullnode.prototype._init = function _init() { // Pool needs access to the chain. this.pool = new bcoin.pool(this, { - witness: this.network.type === 'segnet', + witness: this.network.witness, spv: false }); diff --git a/lib/bcoin/protocol/constants.js b/lib/bcoin/protocol/constants.js index b1d024b5..45f6d271 100644 --- a/lib/bcoin/protocol/constants.js +++ b/lib/bcoin/protocol/constants.js @@ -202,7 +202,7 @@ exports.block = { }; exports.tx = { - version: 1, + version: 2, maxSize: 100000, minFee: 10000, bareMultisig: true, @@ -291,11 +291,9 @@ exports.flags = { VERIFY_DISCOURAGE_UPGRADABLE_NOPS: (1 << 7), VERIFY_CLEANSTACK: (1 << 8), VERIFY_CHECKLOCKTIMEVERIFY: (1 << 9), - VERIFY_WITNESS: (1 << 10), - VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: (1 << 11), - // NOTE: Should be (1 << 10) - but that conflicts with segwit - VERIFY_CHECKSEQUENCEVERIFY: (1 << 12), - + VERIFY_CHECKSEQUENCEVERIFY: (1 << 10), + VERIFY_WITNESS: (1 << 11), + VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: (1 << 12), VERIFY_SEQUENCE: (1 << 0), MEDIAN_TIME_PAST: (1 << 1) }; diff --git a/lib/bcoin/protocol/network.js b/lib/bcoin/protocol/network.js index 7507fe7e..ef1f9b0c 100644 --- a/lib/bcoin/protocol/network.js +++ b/lib/bcoin/protocol/network.js @@ -12,14 +12,14 @@ var utils = require('../utils'); */ var network = exports; -var main, testnet, regtest, segnet; +var main, testnet, regtest, segnet3, segnet4; network.set = function set(type) { var net = network[type]; utils.merge(network, net); }; -network.types = ['main', 'testnet', 'regtest', 'segnet']; +network.types = ['main', 'testnet', 'regtest', 'segnet3', 'segnet4']; /** * Main @@ -364,20 +364,20 @@ regtest.deployments = { regtest.height = -1; /** - * Segnet + * segnet3 */ -segnet = network.segnet = {}; +segnet3 = network.segnet3 = {}; -segnet.type = 'segnet'; +segnet3.type = 'segnet3'; -segnet.prefixes = { +segnet3.prefixes = { privkey: 158, xpubkey: 0x053587cf, xprivkey: 0x05358394 }; -segnet.address = { +segnet3.address = { prefixes: { pubkeyhash: 30, scripthash: 50, @@ -390,40 +390,40 @@ segnet.address = { } }; -segnet.address.prefixesByVal = utils.revMap(segnet.address.prefixes); -segnet.address.versionsByVal = utils.revMap(segnet.address.versions); +segnet3.address.prefixesByVal = utils.revMap(segnet3.address.prefixes); +segnet3.address.versionsByVal = utils.revMap(segnet3.address.versions); -segnet.seeds = [ +segnet3.seeds = [ '104.243.38.34', '104.155.1.158', '119.246.245.241', '46.101.235.82' ]; -segnet.port = 28333; +segnet3.port = 28333; -segnet.alertKey = new Buffer('' +segnet3.alertKey = new Buffer('' + '04302390343f91cc401d56d68b123028bf52e5f' + 'ca1939df127f63c6467cdf9c8e2c14b61104cf8' + '17d0b780da337893ecc4aaff1309e536162dabb' + 'db45200ca2b0a', 'hex'); -segnet.checkpoints = []; +segnet3.checkpoints = []; -segnet.checkpoints = segnet.checkpoints.reduce(function(out, block) { +segnet3.checkpoints = segnet3.checkpoints.reduce(function(out, block) { out[block.height] = utils.revHex(block.hash); return block; }, {}); -segnet.checkpoints.tsLastCheckpoint = 0; -segnet.checkpoints.txsLastCheckpoint = 0; -segnet.checkpoints.txsPerDay = 300; -segnet.checkpoints.lastHeight = 0; +segnet3.checkpoints.tsLastCheckpoint = 0; +segnet3.checkpoints.txsLastCheckpoint = 0; +segnet3.checkpoints.txsPerDay = 300; +segnet3.checkpoints.lastHeight = 0; -segnet.halvingInterval = 210000; +segnet3.halvingInterval = 210000; -segnet.genesis = { +segnet3.genesis = { version: 1, hash: utils.revHex( '0d5b9c518ddf053fcac71730830df4526a9949c08f34acf6a1d30464d22f02aa' @@ -437,49 +437,99 @@ segnet.genesis = { nonce: 0 }; -segnet.magic = 0xcaea962e; +segnet3.magic = 0xcaea962e; -segnet.powLimit = new bn( +segnet3.powLimit = new bn( '00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 'hex' ); -segnet.powTargetTimespan = 14 * 24 * 60 * 60; // two weeks -segnet.powTargetSpacing = 10 * 60; -segnet.powDiffInterval = segnet.powTargetTimespan / segnet.powTargetSpacing | 0; -segnet.powAllowMinDifficultyBlocks = true; -segnet.powNoRetargeting = false; +segnet3.powTargetTimespan = 14 * 24 * 60 * 60; // two weeks +segnet3.powTargetSpacing = 10 * 60; +segnet3.powDiffInterval = segnet3.powTargetTimespan / segnet3.powTargetSpacing | 0; +segnet3.powAllowMinDifficultyBlocks = true; +segnet3.powNoRetargeting = false; -segnet.block = { +segnet3.block = { majorityEnforceUpgrade: 7, majorityRejectOutdated: 9, majorityWindow: 10, bip34height: -1 }; -segnet.segwitHeight = 0; +segnet3.segwitHeight = 0; -segnet.genesisBlock = '0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a7d719856ffff001d000000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000'; +segnet3.genesisBlock = '0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a7d719856ffff001d000000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000'; -segnet.ruleChangeActivationThreshold = 108; -segnet.minerConfirmationWindow = 144; -segnet.deployments = {}; +segnet3.ruleChangeActivationThreshold = 108; +segnet3.minerConfirmationWindow = 144; +segnet3.deployments = {}; -segnet.height = -1; +segnet3.height = -1; +segnet3.witness = true; + +segnet4 = network.segnet4 = {}; + +utils.merge(segnet4, segnet3); + +segnet4.type = 'segnet4'; + +segnet4.seeds = [ + '37.34.48.17' +]; + +segnet4.port = 28901; +segnet4.segwitHeight = -1; +segnet4.magic = 0xc4a1abdc; + +segnet4.powLimit = new bn( + // 512x lower min difficulty than mainnet + '000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', + 'hex' +); + +segnet4.deployments = utils.merge({}, main.deployments, { + witness: { + bit: 1, + startTime: 0, + timeout: 999999999999 + } + // bip109: { + // bit: 28, + // startTime: 1453939200, // Jan 28th, 2016 + // timeout: 1514764800 // Jan 1st, 2018 + // } +}); + +segnet4.genesis = { + version: 1, + hash: 'b291211d4bb2b7e1b7a4758225e69e50104091a637213d033295c010f55ffb18', + prevBlock: '0000000000000000000000000000000000000000000000000000000000000000', + merkleRoot: utils.revHex( + '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b' + ), + ts: 1452831101, + bits: 503447551, + nonce: 0 +}; + +segnet4.genesisBlock = '0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a7d719856ffff011e000000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000'; network.xprivkeys = { '76066276': 'main', '70615956': 'testnet', - '87393172': 'segnet', + '87393172': 'segnet3', 'xprv': 'main', 'tprv': 'testnet', - '2791': 'segnet' + '2791': 'segnet3', + '2791': 'segnet4' }; network.xpubkeys = { '76067358': 'main', '70617039': 'testnet', - '87394255': 'segnet', + '87394255': 'segnet3', 'xpub': 'main', 'tpub': 'testnet', - '2793': 'segnet' + '2793': 'segnet3', + '2793': 'segnet4' }; diff --git a/lib/bcoin/spvnode.js b/lib/bcoin/spvnode.js index 127a1e2a..70744a7d 100644 --- a/lib/bcoin/spvnode.js +++ b/lib/bcoin/spvnode.js @@ -47,7 +47,7 @@ SPVNode.prototype._init = function _init() { }); this.pool = new bcoin.pool(this, { - witness: this.network.type === 'segnet', + witness: this.network.witness, spv: true }); diff --git a/lib/bcoin/walletdb.js b/lib/bcoin/walletdb.js index 0884a082..442d6bdb 100644 --- a/lib/bcoin/walletdb.js +++ b/lib/bcoin/walletdb.js @@ -443,7 +443,7 @@ WalletDB.prototype.create = function create(options, callback) { } done(); } else { - if (bcoin.protocol.network.type === 'segnet') + if (bcoin.protocol.network.witness) options.witness = options.witness !== false; options.provider = new Provider(self); diff --git a/scripts/gen.js b/scripts/gen.js index d30171b6..ebbe6037 100644 --- a/scripts/gen.js +++ b/scripts/gen.js @@ -1,11 +1,12 @@ var bcoin = require('bcoin'); var constants = bcoin.protocol.constants; +var network = bcoin.protocol.network; var utils = bcoin.utils; -var bn = bcoin.bn; +var bn = require('bn.js'); function createGenesisBlock(options) { var parser = bcoin.protocol.parser; - var tx, block; + var tx, block, txRaw, blockRaw; if (!options.flags) { options.flags = new Buffer( @@ -14,12 +15,14 @@ function createGenesisBlock(options) { } if (!options.script) { - options.script = [ - new Buffer('04678afdb0fe5548271967f1a67130b7105cd6a828e039' - + '09a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c3' - + '84df7ba0b8d578a4c702b6bf11d5f', 'hex'), - 'checksig' - ]; + options.script = { + code: [ + new Buffer('04678afdb0fe5548271967f1a67130b7105cd6a828e039' + + '09a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c3' + + '84df7ba0b8d578a4c702b6bf11d5f', 'hex'), + constants.opcodes.OP_CHECKSIG + ] + }; } if (!options.reward) @@ -32,11 +35,13 @@ function createGenesisBlock(options) { hash: utils.toHex(constants.zeroHash), index: 0xffffffff }, - script: [ - new bn(486604799, 'le').toBuffer(), - new bn(4, 'le').toBuffer(), - options.flags - ], + script: { + code: [ + new bn(486604799, 'le').toBuffer(), + new bn(4, 'le').toBuffer(), + options.flags + ] + }, sequence: 0xffffffff }], outputs: [{ @@ -46,29 +51,33 @@ function createGenesisBlock(options) { locktime: 0 }; - tx._raw = bcoin.protocol.framer.tx(tx); + txRaw = bcoin.protocol.framer.tx(tx); + tx._raw = txRaw; + tx._size = txRaw.length; + tx._witnessSize = 0; block = { version: options.version, prevBlock: utils.toHex(constants.zeroHash), - merkleRoot: utils.toHex(utils.dsha256(tx._raw)), + merkleRoot: utils.toHex(utils.dsha256(txRaw)), ts: options.ts, bits: options.bits, nonce: options.nonce, txs: [tx] }; - block._raw = bcoin.protocol.framer.block(block); + blockRaw = bcoin.protocol.framer.block(block); - block = parser.parseBlock(block._raw); + block = parser.parseBlock(blockRaw); - block._hash = utils.dsha256(block._raw.slice(0, 80)); + block._hash = utils.dsha256(blockRaw.slice(0, 80)); block.hash = utils.toHex(block._hash); - block.network = true; + block._raw = blockRaw; + block._size = blockRaw.length; + block._witnessSize = 0; block.height = 0; tx = block.txs[0]; - tx.network = true; tx.height = 0; tx.ts = block.ts; tx._hash = block.merkleRoot; @@ -98,7 +107,7 @@ var regtest = createGenesisBlock({ nonce: 2 }); -var segnet = createGenesisBlock({ +var segnet3 = createGenesisBlock({ version: 1, // ts: 1452368293, ts: 1452831101, @@ -106,10 +115,17 @@ var segnet = createGenesisBlock({ nonce: 0 }); +var segnet4 = createGenesisBlock({ + version: 1, + ts: 1452831101, + bits: utils.toCompact(network.segnet4.powLimit), + nonce: 0 +}); + utils.print(main); utils.print(testnet); utils.print(regtest); -utils.print(segnet); +utils.print(segnet3); utils.print('main hash: %s', utils.revHex(main.hash)); utils.print('main raw: %s', utils.toHex(main._raw)); utils.print(''); @@ -118,5 +134,8 @@ utils.print('testnet raw: %s', utils.toHex(testnet._raw)); utils.print(''); utils.print('regtest hash: %s', utils.revHex(regtest.hash)); utils.print('regtest raw: %s', utils.toHex(regtest._raw)); -utils.print('segnet hash: %s', utils.revHex(segnet.hash)); -utils.print('segnet raw: %s', utils.toHex(segnet._raw)); +utils.print('segnet3 hash: %s', utils.revHex(segnet3.hash)); +utils.print('segnet3 raw: %s', utils.toHex(segnet3._raw)); +utils.print('segnet4 hash: %s', utils.revHex(segnet4.hash)); +utils.print('segnet4 raw: %s', utils.toHex(segnet4._raw)); +utils.print(segnet4);