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.
@@ -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
- let size = node.size
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
- let size = l.size
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 === node.size) return root
886
- if (bytes > node.size) {
887
- bytes -= node.size
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
- if (l.size === bytes) return ite.index
908
- if (l.size > bytes) continue
909
- bytes -= l.size
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.size <= bytes) throw INVALID_OPERATION('Invalid seek')
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, 0)
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) // flags
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) // flags
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercore",
3
- "version": "10.28.10",
3
+ "version": "10.29.0",
4
4
  "description": "Hypercore is a secure, distributed append-only log",
5
5
  "main": "index.js",
6
6
  "scripts": {