-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: handle incoming blob filters (#956)
*You may wish to [review this squashed commit as separate commits][0].* When you receive a blob filter from another peer, this updates their sync states. For example, if you receive a blob filter that says "I only want photo thumbnails", that peer's "wants" bitfield will be reduced. Closes [#682] and [#905]. [0]: https://github.com/digidem/comapeo-core/pull/956/commits [#682]: #682 [#905]: #905
- Loading branch information
Showing
15 changed files
with
423 additions
and
168 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import b4a from 'b4a' | ||
import { discoveryKey } from 'hypercore-crypto' | ||
import Hyperdrive from 'hyperdrive' | ||
import util from 'node:util' | ||
import { TypedEmitter } from 'tiny-typed-emitter' | ||
|
||
/** @typedef {HyperdriveIndexImpl} THyperdriveIndex */ | ||
|
||
/** | ||
* @extends {TypedEmitter<{ 'add-drive': (drive: Hyperdrive) => void }>} | ||
*/ | ||
export class HyperdriveIndexImpl extends TypedEmitter { | ||
/** @type {Map<string, Hyperdrive>} */ | ||
#hyperdrives = new Map() | ||
#writer | ||
#writerKey | ||
/** @param {import('../core-manager/index.js').CoreManager} coreManager */ | ||
constructor(coreManager) { | ||
super() | ||
/** @type {undefined | Hyperdrive} */ | ||
let writer | ||
const corestore = new PretendCorestore({ coreManager }) | ||
const blobIndexCores = coreManager.getCores('blobIndex') | ||
const writerCoreRecord = coreManager.getWriterCore('blobIndex') | ||
this.#writerKey = writerCoreRecord.key | ||
for (const { key } of blobIndexCores) { | ||
// @ts-ignore - we know pretendCorestore is not actually a Corestore | ||
const drive = new Hyperdrive(corestore, key) | ||
// We use the discovery key to derive the id for a drive | ||
this.#hyperdrives.set(getDiscoveryId(key), drive) | ||
if (key.equals(this.#writerKey)) { | ||
writer = drive | ||
} | ||
} | ||
if (!writer) { | ||
throw new Error('Could not find a writer for the blobIndex namespace') | ||
} | ||
this.#writer = writer | ||
|
||
coreManager.on('add-core', ({ key, namespace }) => { | ||
if (namespace !== 'blobIndex') return | ||
// We use the discovery key to derive the id for a drive | ||
const driveId = getDiscoveryId(key) | ||
if (this.#hyperdrives.has(driveId)) return | ||
// @ts-ignore - we know pretendCorestore is not actually a Corestore | ||
const drive = new Hyperdrive(corestore, key) | ||
this.#hyperdrives.set(driveId, drive) | ||
this.emit('add-drive', drive) | ||
}) | ||
} | ||
get writer() { | ||
return this.#writer | ||
} | ||
get writerKey() { | ||
return this.#writerKey | ||
} | ||
[Symbol.iterator]() { | ||
return this.#hyperdrives.values() | ||
} | ||
/** @param {string} driveId */ | ||
get(driveId) { | ||
return this.#hyperdrives.get(driveId) | ||
} | ||
} | ||
|
||
/** | ||
* Implements the `get()` method as used by hyperdrive-next. It returns the | ||
* relevant cores from the Mapeo CoreManager. | ||
*/ | ||
class PretendCorestore { | ||
#coreManager | ||
/** | ||
* @param {object} options | ||
* @param {import('../core-manager/index.js').CoreManager} options.coreManager | ||
*/ | ||
constructor({ coreManager }) { | ||
this.#coreManager = coreManager | ||
} | ||
|
||
/** | ||
* @param {Buffer | { publicKey: Buffer } | { name: string }} opts | ||
* @returns {import('hypercore')<"binary", Buffer> | undefined} | ||
*/ | ||
get(opts) { | ||
if (b4a.isBuffer(opts)) { | ||
opts = { publicKey: opts } | ||
} | ||
if ('key' in opts) { | ||
// @ts-ignore | ||
opts.publicKey = opts.key | ||
} | ||
if ('publicKey' in opts) { | ||
// NB! We should always add blobIndex (Hyperbee) cores to the core manager | ||
// before we use them here. We would only reach the addCore path if the | ||
// blob core is read from the hyperbee header (before it is added to the | ||
// core manager) | ||
return ( | ||
this.#coreManager.getCoreByKey(opts.publicKey) || | ||
this.#coreManager.addCore(opts.publicKey, 'blob').core | ||
) | ||
} else if (opts.name === 'db') { | ||
return this.#coreManager.getWriterCore('blobIndex').core | ||
} else if (opts.name.includes('blobs')) { | ||
return this.#coreManager.getWriterCore('blob').core | ||
} else { | ||
throw new Error( | ||
'Unsupported corestore.get() with opts ' + util.inspect(opts) | ||
) | ||
} | ||
} | ||
|
||
/** no-op */ | ||
close() {} | ||
} | ||
|
||
/** | ||
* @param {Buffer} key Public key of hypercore | ||
* @returns {string} Hex-encoded string of derived discovery key | ||
*/ | ||
function getDiscoveryId(key) { | ||
return discoveryKey(key).toString('hex') | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.