-
Notifications
You must be signed in to change notification settings - Fork 822
Neutrino #1155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Neutrino #1155
Changes from all commits
f035265
23da8ac
6ab4b66
3d2951c
e9aa064
5e2bc49
3e8f061
a6a3a86
9739d20
565d155
dca0400
d6297d4
965c56c
4be3023
4832f54
fdc3f91
d374238
c73dfcf
a8281f6
a2c7aba
7b70e3e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| #!/usr/bin/env node | ||
|
|
||
| 'use strict'; | ||
|
|
||
| console.log('Starting bcoin'); | ||
| process.title = 'bcoin'; | ||
| const Neutrino = require('../lib/node/neutrino'); | ||
|
|
||
| // Doubt in db | ||
| const node = new Neutrino({ | ||
| file: true, | ||
| argv: true, | ||
| env: true, | ||
| logFile: true, | ||
| logConsole: true, | ||
| logLevel: 'debug', | ||
| db: 'leveldb', | ||
| memory: false, | ||
| workers: true, | ||
| loader: require | ||
| }); | ||
|
|
||
| if (!node.config.bool('no-wallet') && !node.has('walletdb')) { | ||
| const plugin = require('../lib/wallet/plugin'); | ||
| node.use(plugin); | ||
| } | ||
|
|
||
| (async () => { | ||
| await node.ensure(); | ||
| await node.open(); | ||
| await node.connect(); | ||
| node.startSync(); | ||
|
|
||
| node.on("full", () => { | ||
| console.log("Full node"); | ||
| }); | ||
| })().catch((err) => { | ||
| console.error(err.stack); | ||
| process.exit(1); | ||
| }); | ||
|
|
||
| process.on('unhandledRejection', (err, promise) => { | ||
| throw err; | ||
| }); | ||
|
|
||
| process.on('SIGINT', async () => { | ||
| await node.close(); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -64,6 +64,8 @@ class Chain extends AsyncEmitter { | |
|
|
||
| this.orphanMap = new BufferMap(); | ||
| this.orphanPrev = new BufferMap(); | ||
|
|
||
| this.getPrunedMap = new BufferMap(); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -583,7 +585,7 @@ class Chain extends AsyncEmitter { | |
| // UASF is now enforced (bip148) (mainnet-only). | ||
| if (this.options.bip148 && this.network === Network.main) { | ||
| if (witness !== thresholdStates.LOCKED_IN | ||
| && witness !== thresholdStates.ACTIVE) { | ||
| && witness !== thresholdStates.ACTIVE) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this change automatic from you linter? The original code doesn't fail the bcoin lint tests, lets leave it alone since it just makes reviewing your work a bit more confusing (there's several nits like this in the PR) |
||
| // The BIP148 MTP check is nonsensical in | ||
| // that it includes the _current_ entry's | ||
| // timestamp. This requires some hackery, | ||
|
|
@@ -1368,7 +1370,17 @@ class Chain extends AsyncEmitter { | |
| } | ||
|
|
||
| // Do we already have this block? | ||
| if (await this.hasEntry(hash)) { | ||
| const existingEntry = await this.getEntry(hash); | ||
|
|
||
| if (existingEntry && this.getPrunedMap.has(hash)) { | ||
| block = block.toBlock(); | ||
| await this.db.updateNeutrinoSave(); | ||
| await this.db.save(existingEntry, block, new CoinView()); | ||
| await this.db.updateNeutrinoSave(); | ||
| return existingEntry; | ||
| } | ||
|
|
||
| if (existingEntry) { | ||
| this.logger.debug('Already have block: %h.', block.hash()); | ||
| throw new VerifyError(block, 'duplicate', 'duplicate', 0); | ||
| } | ||
|
|
@@ -1791,6 +1803,24 @@ class Chain extends AsyncEmitter { | |
| return this.hasEntry(hash); | ||
| } | ||
|
|
||
| async getCFHeaderHeight() { | ||
| return await this.db.getCFHeaderHeight(); | ||
| } | ||
|
|
||
| async saveCFHeaderHeight(height) { | ||
| this.db.neutrinoState.headerHeight = height; | ||
| await this.db.saveNeutrinoState(); | ||
| } | ||
|
|
||
| async getCFilterHeight() { | ||
| return await this.db.getCFilterHeight(); | ||
| } | ||
|
|
||
| async saveCFilterHeight(height) { | ||
| this.db.neutrinoState.filterHeight = height; | ||
| await this.db.saveNeutrinoState(); | ||
| } | ||
|
|
||
| /** | ||
| * Find the corresponding block entry by hash or height. | ||
| * @param {Hash|Number} hash/height | ||
|
|
@@ -1925,6 +1955,33 @@ class Chain extends AsyncEmitter { | |
| return this.db.getBlock(hash); | ||
| } | ||
|
|
||
| async getBlockPeer(hash, filter) { | ||
| let block = await this.db.getBlock(hash); | ||
| if (block) { | ||
| const entry = await this.getEntry(hash); | ||
| assert(entry.hash.equals(hash)); | ||
| return block; | ||
| } else { | ||
| this.logger.warning('Block not found, attempting to download'); | ||
|
|
||
| // Ensure hash not height | ||
| hash = await this.db.getHash(hash); | ||
|
|
||
| const wait = new Promise((resolve, reject) => { | ||
| this.getPrunedMap.set(hash, resolve); | ||
| }); | ||
|
|
||
| await this.emitAsync('getprunedblock', hash); | ||
| await wait; | ||
| block = await this.db.getBlock(hash); | ||
| const entry = await this.getEntry(hash); | ||
| assert(entry.hash.equals(hash)); | ||
|
|
||
| this.emit('getblockpeer', entry, block); | ||
| return block; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Retrieve a block from the database (not filled with coins). | ||
| * @param {Hash} block | ||
|
|
@@ -2007,15 +2064,20 @@ class Chain extends AsyncEmitter { | |
| if (this.height < this.network.lastCheckpoint) | ||
| return; | ||
| } | ||
|
|
||
| if (this.tip.time < util.now() - this.network.block.maxTipAge) | ||
| if (this.options.neutrino && this.tip.time < 1686851917) | ||
| // TODO change this later | ||
| return; | ||
| else if (!this.options.neutrino && | ||
| this.tip.time < util.now() - this.network.block.maxTipAge) | ||
| return; | ||
|
|
||
| if (!this.hasChainwork()) | ||
| return; | ||
|
|
||
| this.synced = true; | ||
| this.emit('full'); | ||
| if (this.options.neutrino) | ||
| this.emit('headersFull'); | ||
| else | ||
| this.emit('full'); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -2144,7 +2206,7 @@ class Chain extends AsyncEmitter { | |
|
|
||
| assert(hash); | ||
|
|
||
| for (;;) { | ||
| for (; ;) { | ||
| const orphan = this.orphanMap.get(hash); | ||
|
|
||
| if (!orphan) | ||
|
|
@@ -2221,8 +2283,8 @@ class Chain extends AsyncEmitter { | |
| return pow.bits; | ||
|
|
||
| while (prev.height !== 0 | ||
| && prev.height % pow.retargetInterval !== 0 | ||
| && prev.bits === pow.bits) { | ||
| && prev.height % pow.retargetInterval !== 0 | ||
| && prev.bits === pow.bits) { | ||
| const cache = this.getPrevCache(prev); | ||
|
|
||
| if (cache) | ||
|
|
@@ -2455,7 +2517,7 @@ class Chain extends AsyncEmitter { | |
| const state = await this.getState(prev, deployment); | ||
|
|
||
| if (state === thresholdStates.LOCKED_IN | ||
| || state === thresholdStates.STARTED) { | ||
| || state === thresholdStates.STARTED) { | ||
| version |= 1 << deployment.bit; | ||
| } | ||
| } | ||
|
|
@@ -2616,6 +2678,7 @@ class ChainOptions { | |
| this.compression = true; | ||
|
|
||
| this.spv = false; | ||
| this.neutrino = false; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm still feeling like we can get away with a chain in SPV mode but a pool in neutrino mode, which might mean we can leave chain.js mostly alone. But I'm just starting to dig in here so I defer to you |
||
| this.bip91 = false; | ||
| this.bip148 = false; | ||
| this.prune = false; | ||
|
|
@@ -2639,7 +2702,7 @@ class ChainOptions { | |
| fromOptions(options) { | ||
| if (!options.spv) { | ||
| assert(options.blocks && typeof options.blocks === 'object', | ||
| 'Chain requires a blockstore.'); | ||
| 'Chain requires a blockstore.'); | ||
| } | ||
|
|
||
| this.blocks = options.blocks; | ||
|
|
@@ -2662,6 +2725,11 @@ class ChainOptions { | |
| this.spv = options.spv; | ||
| } | ||
|
|
||
| if (options.neutrino != null) { | ||
| assert(typeof options.neutrino === 'boolean'); | ||
| this.neutrino = options.neutrino; | ||
| } | ||
|
|
||
| if (options.prefix != null) { | ||
| assert(typeof options.prefix === 'string'); | ||
| this.prefix = options.prefix; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.