blind-peer 0.0.4 → 2.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/db.js ADDED
@@ -0,0 +1,170 @@
1
+ const HyperDB = require('hyperdb')
2
+ const crypto = require('hypercore-crypto')
3
+ const ReadyResource = require('ready-resource')
4
+ const { definition: spec } = require('blind-peer-encodings')
5
+
6
+ // LOW, NORMAL, HIGH
7
+ const MAX_PRIO = 2
8
+
9
+ module.exports = class BlindPeerDB extends ReadyResource {
10
+ constructor (db, auth) {
11
+ super()
12
+
13
+ this.db = HyperDB.rocks(db, spec)
14
+ this.digest = null
15
+ this.auth = auth || null
16
+
17
+ this.encryptionKeyPair = null
18
+ this.swarmingKeyPair = null
19
+
20
+ this.coresAdding = []
21
+ this.coresUpdated = new Map()
22
+
23
+ this.stats = {
24
+ flushes: 0
25
+ }
26
+
27
+ this.ready().catch(noop)
28
+ }
29
+
30
+ find (col, q) {
31
+ return this.db.find(col, q)
32
+ }
33
+
34
+ get (col, q) {
35
+ return this.db.get(col, q)
36
+ }
37
+
38
+ getCoreRecord (key) {
39
+ return this.get('@blind-peer/cores', { key })
40
+ }
41
+
42
+ async _open () {
43
+ await this.db.ready()
44
+
45
+ const auth = await this.db.get('@blind-peer/auth')
46
+
47
+ this.auth = auth || this.auth || { swarming: null, encryption: null }
48
+ if (!this.auth.encryption) this.auth.encryption = crypto.randomBytes(32)
49
+ if (!this.auth.swarming) this.auth.swarming = crypto.randomBytes(32)
50
+
51
+ this.encryptionKeyPair = crypto.encryptionKeyPair(this.auth.encryption)
52
+ this.swarmingKeyPair = crypto.keyPair(this.auth.swarming)
53
+
54
+ const digest = await this.db.get('@blind-peer/digest')
55
+
56
+ this.digest = digest || { referrers: 0, cores: 0, bytesAllocated: 0, flushed: false }
57
+ this.digest.flushed = false
58
+
59
+ await this.db.insert('@blind-peer/auth', this.auth)
60
+ await this.db.insert('@blind-peer/digest', this.digest)
61
+ await this.db.flush()
62
+ }
63
+
64
+ async flush () { // The caller is responsible for ensuring this runs in a lock
65
+ if (!this.opened) await this.ready()
66
+
67
+ const coresAdding = this.coresAdding
68
+ const coresUpdated = this.coresUpdated
69
+
70
+ this.coresAdding = []
71
+ this.coresUpdated = new Map()
72
+
73
+ const tx = this.db.transaction()
74
+ const time = Date.now()
75
+
76
+ let addedCores = 0
77
+ let addedReferrers = 0
78
+ let bytesAllocated = 0
79
+
80
+ for (const info of coresAdding) {
81
+ const key = info.key
82
+ const existing = await tx.get('@blind-peer/cores', { key })
83
+ // TODO: test this path
84
+ if (existing) {
85
+ if (!info.announce && (info.priority || 0) <= existing.priority) continue // would be a downgrade, which we never want
86
+
87
+ existing.priority = Math.min(
88
+ Math.max(info.priority || 0, existing.priority)
89
+ )
90
+ existing.announce = info.announce || existing.announce
91
+ existing.updated = time
92
+ existing.active = time
93
+ await tx.insert('@blind-peer/cores', existing)
94
+ } else {
95
+ await tx.insert('@blind-peer/cores', {
96
+ key,
97
+ length: 0,
98
+ bytesAllocated: 0,
99
+ updated: time,
100
+ active: time,
101
+ priority: Math.min(MAX_PRIO, info.priority || 0),
102
+ announce: !!info.announce,
103
+ referrer: info.referrer || null,
104
+ blocksCleared: 0,
105
+ bytesCleared: 0
106
+ })
107
+
108
+ addedCores++
109
+ if (info.referrer) addedReferrers++
110
+ }
111
+ }
112
+
113
+ for (const core of coresUpdated.values()) {
114
+ const c = await tx.get('@blind-peer/cores', { key: core.key })
115
+ if (!c) continue // state mismatch
116
+
117
+ const updated = c.length !== core.length
118
+
119
+ bytesAllocated += (core.bytesAllocated - c.bytesAllocated)
120
+
121
+ c.length = core.length
122
+ c.bytesAllocated = core.bytesAllocated
123
+ c.bytesCleared = core.bytesCleared || 0
124
+ if (updated) c.updated = time
125
+ c.active = time
126
+ c.blocksCleared = core.blocksCleared || 0
127
+
128
+ await tx.insert('@blind-peer/cores', c)
129
+ }
130
+
131
+ if (addedCores || addedReferrers || bytesAllocated || this.closing) {
132
+ this.stats.flushes++ // we only count those flushes where we update the db
133
+
134
+ this.digest.cores += addedCores
135
+ this.digest.referrers += addedReferrers
136
+ this.digest.bytesAllocated += bytesAllocated
137
+ this.digest.flushed = !!this.closing
138
+
139
+ await tx.insert('@blind-peer/digest', this.digest)
140
+ }
141
+
142
+ await tx.flush()
143
+ }
144
+
145
+ addCore (info) {
146
+ this.coresAdding.push(info)
147
+ }
148
+
149
+ updateCore (core, id) { // TODO: id is technically optional
150
+ this.coresUpdated.set(id, core)
151
+ }
152
+
153
+ updated () {
154
+ return this.coresAdding.length > 0 || this.coresUpdated.size > 0
155
+ }
156
+
157
+ createGcCandidateReadStream () {
158
+ return this.db.find('@blind-peer/cores-by-activity')
159
+ }
160
+
161
+ createAnnouncingCoresStream () {
162
+ return this.db.find('@blind-peer/cores-by-announce')
163
+ }
164
+
165
+ async _close () {
166
+ await this.db.close()
167
+ }
168
+ }
169
+
170
+ function noop () {}
package/package.json CHANGED
@@ -1,37 +1,62 @@
1
1
  {
2
2
  "name": "blind-peer",
3
- "version": "0.0.4",
4
- "description": "WIP - nothing to see here",
3
+ "version": "2.7.5",
4
+ "description": "Blind peers help keep hypercores available",
5
5
  "main": "index.js",
6
6
  "bin": {
7
7
  "blind-peer": "bin.js"
8
8
  },
9
9
  "dependencies": {
10
- "autobase-light-writer": "^1.1.0",
11
- "corestore": "^6.18.4",
12
- "graceful-goodbye": "^1.3.2",
10
+ "autobase": "^7.0.18",
11
+ "autobase-discovery": "^1.0.0",
12
+ "b4a": "^1.6.7",
13
+ "blind-peer-encodings": "^3.0.0",
14
+ "compact-encoding": "^2.16.0",
15
+ "corestore": "^7.4.4",
16
+ "graceful-goodbye": "^1.3.3",
17
+ "hyper-instrument": "^2.0.0",
18
+ "hypercore": "^11.0.12",
19
+ "hypercore-crypto": "^3.5.0",
13
20
  "hypercore-id-encoding": "^1.3.0",
14
- "hyperdb": "^4.1.2",
15
- "hyperschema": "^1.0.3",
21
+ "hyperdb": "^4.9.4",
22
+ "hyperschema": "^1.10.3",
16
23
  "hyperswarm": "^4.8.4",
17
- "paparam": "^1.6.1",
18
- "protomux-rpc": "^1.6.0"
24
+ "paparam": "^1.8.0",
25
+ "pino": "^9.6.0",
26
+ "protomux-rpc": "^1.7.1",
27
+ "protomux-wakeup": "^2.2.0",
28
+ "ready-resource": "^1.1.2",
29
+ "repl-swarm": "^2.2.0",
30
+ "rocksdb-native": "^3.1.6",
31
+ "safety-catch": "^1.0.2",
32
+ "scope-lock": "^1.2.4",
33
+ "tiny-byte-size": "^1.1.0"
19
34
  },
20
35
  "devDependencies": {
36
+ "blind-peering": "^1.10.1",
37
+ "brittle": "^3.7.0",
21
38
  "debounceify": "^1.1.0",
22
- "standard": "^17.1.2"
39
+ "hyperdht": "^6.20.1",
40
+ "prom-client": "^15.1.3",
41
+ "standard": "^17.1.2",
42
+ "test-tmp": "^1.3.0"
23
43
  },
44
+ "files": [
45
+ "bin.js",
46
+ "index.js",
47
+ "lib/"
48
+ ],
24
49
  "scripts": {
25
- "test": "standard"
50
+ "test": "standard && brittle test/*.js"
26
51
  },
27
52
  "repository": {
28
53
  "type": "git",
29
- "url": "https://github.com/mafintosh/blind-peer.git"
54
+ "url": "git+https://github.com/holepunchto/blind-peer.git"
30
55
  },
31
56
  "author": "Holepunch Inc.",
32
57
  "license": "Apache-2.0",
33
58
  "bugs": {
34
- "url": "https://github.com/mafintosh/blind-peer/issues"
59
+ "url": "https://github.com/holepunchto/blind-peer/issues"
35
60
  },
36
- "homepage": "https://github.com/mafintosh/blind-peer"
61
+ "homepage": "https://github.com/holepunchto/blind-peer"
37
62
  }
@@ -1,23 +0,0 @@
1
- name: Build Status
2
- on:
3
- push:
4
- branches:
5
- - main
6
- pull_request:
7
- branches:
8
- - main
9
- jobs:
10
- build:
11
- strategy:
12
- matrix:
13
- node-version: [lts/*]
14
- os: [ubuntu-latest, macos-latest, windows-latest]
15
- runs-on: ${{ matrix.os }}
16
- steps:
17
- - uses: actions/checkout@v3
18
- - name: Use Node.js ${{ matrix.node-version }}
19
- uses: actions/setup-node@v3
20
- with:
21
- node-version: ${{ matrix.node-version }}
22
- - run: npm install
23
- - run: npm test
package/build.js DELETED
@@ -1,102 +0,0 @@
1
- const HyperDB = require('hyperdb/builder')
2
- const Hyperschema = require('hyperschema')
3
-
4
- const SCHEMA_DIR = './spec/hyperschema'
5
- const DB_DIR = './spec/hyperdb'
6
-
7
- const schema = Hyperschema.from(SCHEMA_DIR)
8
- const blind = schema.namespace('blind-peer')
9
-
10
- blind.register({
11
- name: 'request-mailbox',
12
- fields: [
13
- {
14
- name: 'autobase',
15
- type: 'fixed32',
16
- required: true
17
- },
18
- {
19
- name: 'blockEncryptionKey',
20
- type: 'fixed32'
21
- }
22
- ]
23
- })
24
-
25
- blind.register({
26
- name: 'response-mailbox',
27
- fields: [
28
- {
29
- name: 'autobase',
30
- type: 'fixed32',
31
- required: true
32
- },
33
- {
34
- name: 'writer',
35
- type: 'fixed32',
36
- required: true
37
- },
38
- {
39
- name: 'open',
40
- type: 'bool'
41
- }
42
- ]
43
- })
44
-
45
- blind.register({
46
- name: 'request-post',
47
- fields: [
48
- {
49
- name: 'autobase',
50
- type: 'fixed32',
51
- required: true
52
- },
53
- {
54
- name: 'message',
55
- type: 'buffer'
56
- }
57
- ]
58
- })
59
-
60
- blind.register({
61
- name: 'response-post',
62
- fields: [
63
- {
64
- name: 'length',
65
- type: 'uint',
66
- required: true
67
- }
68
- ]
69
- })
70
-
71
- blind.register({
72
- name: 'mailbox',
73
- fields: [
74
- {
75
- name: 'autobase',
76
- type: 'fixed32',
77
- required: true
78
- },
79
- {
80
- name: 'writer',
81
- type: 'fixed32',
82
- required: true
83
- },
84
- {
85
- name: 'blockEncryptionKey',
86
- type: 'fixed32'
87
- }
88
- ]
89
- })
90
-
91
- Hyperschema.toDisk(schema)
92
-
93
- const db = HyperDB.from(SCHEMA_DIR, DB_DIR, { offset: 64 })
94
- const blindDB = db.namespace('blind-peer')
95
-
96
- blindDB.collections.register({
97
- name: 'mailbox',
98
- schema: '@blind-peer/mailbox',
99
- key: ['autobase']
100
- })
101
-
102
- HyperDB.toDisk(db)
package/client.js DELETED
@@ -1,31 +0,0 @@
1
- const schema = require('./spec/hyperschema')
2
- const c = require('compact-encoding')
3
- const ProtomuxRPC = require('protomux-rpc')
4
-
5
- const addMailboxEncoding = {
6
- requestEncoding: schema.resolveStruct('@blind-peer/request-mailbox'),
7
- responseEncoding: schema.resolveStruct('@blind-peer/response-mailbox')
8
- }
9
-
10
- const postEncoding = {
11
- requestEncoding: schema.resolveStruct('@blind-peer/request-post'),
12
- responseEncoding: schema.resolveStruct('@blind-peer/response-post')
13
- }
14
-
15
- module.exports = class BlindPeerClient {
16
- constructor (stream) {
17
- this.stream = stream
18
- this.rpc = new ProtomuxRPC(stream, {
19
- id: stream.remotePublicKey,
20
- valueEncoding: c.none
21
- })
22
- }
23
-
24
- addMailbox (data) {
25
- return this.rpc.request('add-mailbox', data, addMailboxEncoding)
26
- }
27
-
28
- post ({ autobase, message }) {
29
- return this.rpc.request('post', { autobase, message }, postEncoding)
30
- }
31
- }
@@ -1,66 +0,0 @@
1
- import BlindPeerClient from '../client.js'
2
- import Autobase from 'autobase'
3
- import c from 'compact-encoding'
4
- import Corestore from 'corestore'
5
- import Hyperswarm from 'hyperswarm'
6
- import debounce from 'debounceify'
7
- import IdEnc from 'hypercore-id-encoding'
8
-
9
- const base = new Autobase(new Corestore('/tmp/my-corestore'), {
10
- encryptionKey: Buffer.alloc(30).fill('secret'),
11
- open (store) {
12
- return store.get('view', { valueEncoding: c.json })
13
- },
14
- async apply (nodes, view, base) {
15
- for (const node of nodes) {
16
- const jsonValue = JSON.parse(node.value.toString())
17
- if (jsonValue.add) await base.addWriter(Buffer.from(jsonValue.key, 'hex'), { indexer: false })
18
- view.append(jsonValue)
19
- }
20
- }
21
- })
22
-
23
- await base.ready()
24
- console.log('Autobase:', base.key.toString('hex'))
25
-
26
- base.view.on('append', debounce(async function () {
27
- base.ack() // ack for good messure
28
- console.log('someone appended to the autobase!')
29
- for (let i = 0; i < base.view.length; i++) {
30
- console.log(i, await base.view.get(i))
31
- }
32
- }))
33
-
34
- // TODO: record in autobase
35
- const publicKey = IdEnc.decode(process.argv[2])
36
-
37
- const s = new Hyperswarm({ keyPair: await base.store.createKeyPair('tmp') })
38
-
39
- s.on('connection', async c => {
40
- base.store.replicate(c)
41
-
42
- if (!c.remotePublicKey.equals(publicKey)) return
43
-
44
- const peer = new BlindPeerClient(c)
45
-
46
- const info = await peer.addMailbox({ autobase: base.key })
47
-
48
- if (info.open === false) {
49
- const message = Buffer.from(
50
- JSON.stringify({ add: true, key: info.writer.toString('hex') })
51
- )
52
- await base.append(message)
53
- await base.update()
54
-
55
- const core = base.store.get({ key: info.writer, active: false })
56
- await core.setEncryptionKey(base.encryptionKey)
57
- const req = { autobase: base.key, blockEncryptionKey: core.encryption.blockKey }
58
- await core.close()
59
-
60
- await peer.addMailbox(req)
61
-
62
- console.log('opened mailbox...')
63
- }
64
- })
65
-
66
- s.joinPeer(publicKey)
@@ -1,6 +0,0 @@
1
- import BlindPeer from '../index.js'
2
-
3
- const m = new BlindPeer('/tmp/blind-peer')
4
- await m.listen()
5
-
6
- console.log(m.publicKey.toString('hex'))
package/example/post.mjs DELETED
@@ -1,25 +0,0 @@
1
- import BlindPeerClient from '../client.js'
2
- import Hyperswarm from 'hyperswarm'
3
- import IdEnc from 'hypercore-id-encoding'
4
-
5
- const publicKey = IdEnc.decode(process.argv[2])
6
- const autobase = IdEnc.decode(process.argv[3])
7
- const rawMessage = process.argv[4]
8
- const message = Buffer.from(
9
- JSON.stringify({ mailbox: true, message: rawMessage })
10
- )
11
-
12
- const s = new Hyperswarm()
13
-
14
- s.on('connection', async c => {
15
- if (!c.remotePublicKey.equals(publicKey)) return
16
-
17
- const peer = new BlindPeerClient(c)
18
- const reply = await peer.post({ autobase, message })
19
-
20
- console.log(reply)
21
-
22
- s.destroy()
23
- })
24
-
25
- s.joinPeer(publicKey)
@@ -1,19 +0,0 @@
1
- {
2
- "version": 0,
3
- "offset": 64,
4
- "schema": [
5
- {
6
- "name": "mailbox",
7
- "namespace": "blind-peer",
8
- "id": 64,
9
- "type": 1,
10
- "indexes": [],
11
- "schema": "@blind-peer/mailbox",
12
- "derived": false,
13
- "key": [
14
- "autobase"
15
- ],
16
- "trigger": null
17
- }
18
- ]
19
- }
@@ -1,83 +0,0 @@
1
- // This file is autogenerated by the hyperdb compiler
2
- /* eslint-disable camelcase */
3
-
4
- const { IndexEncoder, c } = require('hyperdb/runtime')
5
-
6
- const { version, resolveStruct } = require('./messages.js')
7
-
8
- // '@blind-peer/mailbox' collection key
9
- const collection64_key = new IndexEncoder([
10
- IndexEncoder.BUFFER
11
- ], { prefix: 64 })
12
-
13
- function collection64_indexify (record) {
14
- const a = record.autobase
15
- return a === undefined ? [] : [a]
16
- }
17
-
18
- // '@blind-peer/mailbox' reconstruction function
19
- function collection64_reconstruct (version, keyBuf, valueBuf) {
20
- const key = collection64_key.decode(keyBuf)
21
- const value = c.decode(resolveStruct('@blind-peer/mailbox/value', version), valueBuf)
22
- // TODO: This should be fully code generated
23
- return {
24
- autobase: key[0],
25
- ...value
26
- }
27
- }
28
- // '@blind-peer/mailbox' key reconstruction function
29
- function collection64_reconstruct_key (keyBuf) {
30
- const key = collection64_key.decode(keyBuf)
31
- return {
32
- autobase: key[0]
33
- }
34
- }
35
-
36
- // '@blind-peer/mailbox'
37
- const collection64 = {
38
- name: '@blind-peer/mailbox',
39
- id: 64,
40
- encodeKey (record) {
41
- const key = [record.autobase]
42
- return collection64_key.encode(key)
43
- },
44
- encodeKeyRange ({ gt, lt, gte, lte } = {}) {
45
- return collection64_key.encodeRange({
46
- gt: gt ? collection64_indexify(gt) : null,
47
- lt: lt ? collection64_indexify(lt) : null,
48
- gte: gte ? collection64_indexify(gte) : null,
49
- lte: lte ? collection64_indexify(lte) : null
50
- })
51
- },
52
- encodeValue (version, record) {
53
- return c.encode(resolveStruct('@blind-peer/mailbox/value', version), record)
54
- },
55
- trigger: null,
56
- reconstruct: collection64_reconstruct,
57
- reconstructKey: collection64_reconstruct_key,
58
- indexes: []
59
- }
60
-
61
- module.exports = {
62
- version,
63
- collections: [
64
- collection64
65
- ],
66
- indexes: [
67
- ],
68
- resolveCollection,
69
- resolveIndex
70
- }
71
-
72
- function resolveCollection (name) {
73
- switch (name) {
74
- case '@blind-peer/mailbox': return collection64
75
- default: return null
76
- }
77
- }
78
-
79
- function resolveIndex (name) {
80
- switch (name) {
81
- default: return null
82
- }
83
- }