hypercore 10.28.10 → 10.29.0
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/merkle-tree.js +23 -19
- package/lib/messages.js +8 -4
- package/lib/replicator.js +6 -3
- package/package.json +1 -1
package/lib/merkle-tree.js
CHANGED
|
@@ -345,8 +345,7 @@ class ByteSeeker {
|
|
|
345
345
|
if (!bytes) return [0, 0]
|
|
346
346
|
|
|
347
347
|
for (const node of this.tree.roots) { // all async ticks happen once we find the root so safe
|
|
348
|
-
|
|
349
|
-
if (this.padding > 0) size -= this.padding * flat.countLeaves(node.index)
|
|
348
|
+
const size = getUnpaddedSize(node, this.padding, null)
|
|
350
349
|
|
|
351
350
|
if (bytes === size) return [flat.rightSpan(node.index) + 2, 0]
|
|
352
351
|
if (bytes > size) {
|
|
@@ -359,8 +358,7 @@ class ByteSeeker {
|
|
|
359
358
|
while ((ite.index & 1) !== 0) {
|
|
360
359
|
const l = await this.tree.get(ite.leftChild(), false)
|
|
361
360
|
if (l) {
|
|
362
|
-
|
|
363
|
-
if (this.padding > 0) size -= this.padding * ite.countLeaves()
|
|
361
|
+
const size = getUnpaddedSize(l, this.padding, ite)
|
|
364
362
|
|
|
365
363
|
if (size === bytes) return [ite.rightSpan() + 2, 0]
|
|
366
364
|
if (size > bytes) continue
|
|
@@ -875,20 +873,21 @@ function verifyUpgrade ({ fork, upgrade }, blockRoot, batch) {
|
|
|
875
873
|
return q.extra === null
|
|
876
874
|
}
|
|
877
875
|
|
|
878
|
-
async function seekFromHead (tree, head, bytes) {
|
|
876
|
+
async function seekFromHead (tree, head, bytes, padding) {
|
|
879
877
|
const roots = flat.fullRoots(head)
|
|
880
878
|
|
|
881
879
|
for (let i = 0; i < roots.length; i++) {
|
|
882
880
|
const root = roots[i]
|
|
883
881
|
const node = await tree.get(root)
|
|
882
|
+
const size = getUnpaddedSize(node, padding, null)
|
|
884
883
|
|
|
885
|
-
if (bytes ===
|
|
886
|
-
if (bytes >
|
|
887
|
-
bytes -=
|
|
884
|
+
if (bytes === size) return root
|
|
885
|
+
if (bytes > size) {
|
|
886
|
+
bytes -= size
|
|
888
887
|
continue
|
|
889
888
|
}
|
|
890
889
|
|
|
891
|
-
return seekTrustedTree(tree, root, bytes)
|
|
890
|
+
return seekTrustedTree(tree, root, bytes, padding)
|
|
892
891
|
}
|
|
893
892
|
|
|
894
893
|
return head
|
|
@@ -896,7 +895,7 @@ async function seekFromHead (tree, head, bytes) {
|
|
|
896
895
|
|
|
897
896
|
// trust that bytes are within the root tree and find the block at bytes
|
|
898
897
|
|
|
899
|
-
async function seekTrustedTree (tree, root, bytes) {
|
|
898
|
+
async function seekTrustedTree (tree, root, bytes, padding) {
|
|
900
899
|
if (!bytes) return root
|
|
901
900
|
|
|
902
901
|
const ite = flat.iterator(root)
|
|
@@ -904,9 +903,10 @@ async function seekTrustedTree (tree, root, bytes) {
|
|
|
904
903
|
while ((ite.index & 1) !== 0) {
|
|
905
904
|
const l = await tree.get(ite.leftChild(), false)
|
|
906
905
|
if (l) {
|
|
907
|
-
|
|
908
|
-
if (
|
|
909
|
-
bytes
|
|
906
|
+
const size = getUnpaddedSize(l, padding, ite)
|
|
907
|
+
if (size === bytes) return ite.index
|
|
908
|
+
if (size > bytes) continue
|
|
909
|
+
bytes -= size
|
|
910
910
|
ite.sibling()
|
|
911
911
|
} else {
|
|
912
912
|
ite.parent()
|
|
@@ -919,8 +919,8 @@ async function seekTrustedTree (tree, root, bytes) {
|
|
|
919
919
|
|
|
920
920
|
// try to find the block at bytes without trusting that is *is* within the root passed
|
|
921
921
|
|
|
922
|
-
async function seekUntrustedTree (tree, root, bytes) {
|
|
923
|
-
const offset = await tree.byteOffset(root)
|
|
922
|
+
async function seekUntrustedTree (tree, root, bytes, padding) {
|
|
923
|
+
const offset = await tree.byteOffset(root) - (padding ? padding * flat.leftSpan(root) / 2 : 0)
|
|
924
924
|
|
|
925
925
|
if (offset > bytes) throw INVALID_OPERATION('Invalid seek')
|
|
926
926
|
if (offset === bytes) return root
|
|
@@ -929,9 +929,9 @@ async function seekUntrustedTree (tree, root, bytes) {
|
|
|
929
929
|
|
|
930
930
|
const node = await tree.get(root)
|
|
931
931
|
|
|
932
|
-
if (node
|
|
932
|
+
if (getUnpaddedSize(node, padding, null) <= bytes) throw INVALID_OPERATION('Invalid seek')
|
|
933
933
|
|
|
934
|
-
return seekTrustedTree(tree, root, bytes)
|
|
934
|
+
return seekTrustedTree(tree, root, bytes, padding)
|
|
935
935
|
}
|
|
936
936
|
|
|
937
937
|
// Below is proof production, ie, construct proofs to verify a request
|
|
@@ -1212,10 +1212,10 @@ async function generateProof (tree, block, hash, seek, upgrade) {
|
|
|
1212
1212
|
|
|
1213
1213
|
if (node !== null && (!upgrade || node.lastIndex < upgrade.start)) {
|
|
1214
1214
|
subTree = nodesToRoot(node.index, node.nodes, to)
|
|
1215
|
-
const seekRoot = seek ? await seekUntrustedTree(tree, subTree, seek.bytes) : head
|
|
1215
|
+
const seekRoot = seek ? await seekUntrustedTree(tree, subTree, seek.bytes, seek.padding) : head
|
|
1216
1216
|
blockAndSeekProof(tree, node, seek, seekRoot, subTree, p)
|
|
1217
1217
|
} else if ((node || seek) && upgrade) {
|
|
1218
|
-
subTree = seek ? await seekFromHead(tree, to, seek.bytes) : node.index
|
|
1218
|
+
subTree = seek ? await seekFromHead(tree, to, seek.bytes, seek.padding) : node.index
|
|
1219
1219
|
}
|
|
1220
1220
|
|
|
1221
1221
|
if (upgrade) {
|
|
@@ -1257,3 +1257,7 @@ async function generateProof (tree, block, hash, seek, upgrade) {
|
|
|
1257
1257
|
|
|
1258
1258
|
return result
|
|
1259
1259
|
}
|
|
1260
|
+
|
|
1261
|
+
function getUnpaddedSize (node, padding, ite) {
|
|
1262
|
+
return padding === 0 ? node.size : node.size - padding * (ite ? ite.countLeaves() : flat.countLeaves(node.index))
|
|
1263
|
+
}
|
package/lib/messages.js
CHANGED
|
@@ -165,16 +165,17 @@ const wire = exports.wire = {}
|
|
|
165
165
|
|
|
166
166
|
wire.handshake = {
|
|
167
167
|
preencode (state, m) {
|
|
168
|
-
c.uint.preencode(state,
|
|
168
|
+
c.uint.preencode(state, 1)
|
|
169
169
|
c.fixed32.preencode(state, m.capability)
|
|
170
170
|
},
|
|
171
171
|
encode (state, m) {
|
|
172
|
-
c.uint.encode(state, 0)
|
|
172
|
+
c.uint.encode(state, m.seeks ? 1 : 0)
|
|
173
173
|
c.fixed32.encode(state, m.capability)
|
|
174
174
|
},
|
|
175
175
|
decode (state) {
|
|
176
|
-
c.uint.decode(state)
|
|
176
|
+
const flags = c.uint.decode(state)
|
|
177
177
|
return {
|
|
178
|
+
seeks: (flags & 1) !== 0,
|
|
178
179
|
capability: c.fixed32.decode(state)
|
|
179
180
|
}
|
|
180
181
|
}
|
|
@@ -200,13 +201,16 @@ const requestBlock = {
|
|
|
200
201
|
const requestSeek = {
|
|
201
202
|
preencode (state, s) {
|
|
202
203
|
c.uint.preencode(state, s.bytes)
|
|
204
|
+
c.uint.preencode(state, s.padding)
|
|
203
205
|
},
|
|
204
206
|
encode (state, s) {
|
|
205
207
|
c.uint.encode(state, s.bytes)
|
|
208
|
+
c.uint.encode(state, s.padding)
|
|
206
209
|
},
|
|
207
210
|
decode (state) {
|
|
208
211
|
return {
|
|
209
|
-
bytes: c.uint.decode(state)
|
|
212
|
+
bytes: c.uint.decode(state),
|
|
213
|
+
padding: c.uint.decode(state)
|
|
210
214
|
}
|
|
211
215
|
}
|
|
212
216
|
}
|
package/lib/replicator.js
CHANGED
|
@@ -269,6 +269,7 @@ class Peer {
|
|
|
269
269
|
this.stream = protomux.stream
|
|
270
270
|
this.protomux = protomux
|
|
271
271
|
this.remotePublicKey = this.stream.remotePublicKey
|
|
272
|
+
this.remoteSupportsSeeks = false
|
|
272
273
|
|
|
273
274
|
this.paused = false
|
|
274
275
|
|
|
@@ -389,7 +390,7 @@ class Peer {
|
|
|
389
390
|
})
|
|
390
391
|
}
|
|
391
392
|
|
|
392
|
-
onopen ({ capability }) {
|
|
393
|
+
onopen ({ seeks, capability }) {
|
|
393
394
|
const expected = caps.replicate(this.stream.isInitiator === false, this.replicator.key, this.stream.handshakeHash)
|
|
394
395
|
|
|
395
396
|
if (b4a.equals(capability, expected) !== true) { // TODO: change this to a rejection instead, less leakage
|
|
@@ -398,6 +399,7 @@ class Peer {
|
|
|
398
399
|
|
|
399
400
|
if (this.remoteOpened === true) return
|
|
400
401
|
this.remoteOpened = true
|
|
402
|
+
this.remoteSupportsSeeks = seeks
|
|
401
403
|
|
|
402
404
|
this.protomux.cork()
|
|
403
405
|
|
|
@@ -821,7 +823,7 @@ class Peer {
|
|
|
821
823
|
// We need an upgrade for the seek, if non can be provided, skip
|
|
822
824
|
if (req === null) return false
|
|
823
825
|
|
|
824
|
-
req.seek = { bytes: s.seeker.bytes }
|
|
826
|
+
req.seek = this.remoteSupportsSeeks ? { bytes: s.seeker.bytes, padding: s.seeker.padding } : null
|
|
825
827
|
|
|
826
828
|
s.inflight.push(req)
|
|
827
829
|
this._send(req)
|
|
@@ -851,7 +853,7 @@ class Peer {
|
|
|
851
853
|
const req = this._makeRequest(false, h.priority)
|
|
852
854
|
|
|
853
855
|
req.hash = { index: 2 * index, nodes: 0 }
|
|
854
|
-
req.seek = { bytes: s.seeker.bytes }
|
|
856
|
+
req.seek = this.remoteSupportsSeeks ? { bytes: s.seeker.bytes, padding: s.seeker.padding } : null
|
|
855
857
|
|
|
856
858
|
s.inflight.push(req)
|
|
857
859
|
h.inflight.push(req)
|
|
@@ -1921,6 +1923,7 @@ module.exports = class Replicator {
|
|
|
1921
1923
|
const stream = protomux.stream
|
|
1922
1924
|
|
|
1923
1925
|
peer.channel.open({
|
|
1926
|
+
seeks: true,
|
|
1924
1927
|
capability: caps.replicate(stream.isInitiator, this.key, stream.handshakeHash)
|
|
1925
1928
|
})
|
|
1926
1929
|
|