hypercore 10.31.12 → 10.32.1

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/messages.js CHANGED
@@ -65,76 +65,120 @@ const signer = {
65
65
 
66
66
  const signerArray = c.array(signer)
67
67
 
68
- const multipleSigners = {
69
- preencode (state, m) {
70
- state.end++ // flags
71
- c.uint.preencode(state, m.quorum)
72
- signerArray.preencode(state, m.signers)
68
+ const prologue = {
69
+ preencode (state, p) {
70
+ c.fixed32.preencode(state, p.hash)
71
+ c.uint.preencode(state, p.length)
73
72
  },
74
- encode (state, m) {
75
- c.uint.encode(state, m.allowPatched ? 1 : 0)
76
- c.uint.encode(state, m.quorum)
77
- signerArray.encode(state, m.signers)
73
+ encode (state, p) {
74
+ c.fixed32.encode(state, p.hash)
75
+ c.uint.encode(state, p.length)
78
76
  },
79
77
  decode (state) {
80
- const flags = c.uint.decode(state)
81
78
  return {
82
- allowPatched: (flags & 1) !== 0,
83
- quorum: c.uint.decode(state),
84
- signers: signerArray.decode(state)
79
+ hash: c.fixed32.decode(state),
80
+ length: c.uint.decode(state)
85
81
  }
86
82
  }
87
83
  }
88
84
 
89
- const manifest = exports.manifest = {
85
+ const manifestv0 = {
90
86
  preencode (state, m) {
91
- c.uint.preencode(state, 0) // version
92
87
  hashes.preencode(state, m.hash)
93
- c.uint.preencode(state, 2) // type
94
-
95
- if (m.static) {
96
- c.fixed32.preencode(state, m.static)
97
- }
98
-
99
- if (m.signer) {
100
- signer.preencode(state, m.signer)
101
- }
102
-
103
- if (m.multipleSigners) {
104
- multipleSigners.preencode(state, m.multipleSigners)
88
+ state.end++ // type
89
+
90
+ if (m.quorum === 1 && m.signers.length === 1 && !m.allowPatch) {
91
+ signer.preencode(state, m.signers[0])
92
+ } else {
93
+ state.end++ // flags
94
+ c.uint.preencode(state, m.quorum)
95
+ signerArray.preencode(state, m.signers)
105
96
  }
106
97
  },
107
98
  encode (state, m) {
108
- c.uint.encode(state, 0) // version
109
99
  hashes.encode(state, m.hash)
110
- c.uint.encode(state, m.signer ? 1 : m.multipleSigners ? 2 : 0)
111
100
 
112
- if (m.static) {
113
- c.fixed32.encode(state, m.static)
101
+ if (m.quorum === 1 && m.signers.length === 1 && !m.allowPatch) {
102
+ c.uint.encode(state, 1)
103
+ signer.encode(state, m.signers[0])
104
+ } else {
105
+ c.uint.encode(state, 2)
106
+ c.uint.encode(state, m.allowPatched ? 1 : 0)
107
+ c.uint.encode(state, m.quorum)
108
+ signerArray.encode(state, m.signers)
114
109
  }
110
+ },
111
+ decode (state) {
112
+ const hash = hashes.decode(state)
113
+ const type = c.uint.decode(state)
114
+
115
+ if (type === 0) throw new Error('Type 0 is deprecated')
116
+ if (type > 2) throw new Error('Unknown type: ' + type)
115
117
 
116
- if (m.signer) {
117
- signer.encode(state, m.signer)
118
+ if (type === 1) {
119
+ return {
120
+ version: 0,
121
+ hash,
122
+ allowPatch: false,
123
+ quorum: 1,
124
+ signers: [signer.decode(state)],
125
+ prologue: null
126
+ }
118
127
  }
119
128
 
120
- if (m.multipleSigners) {
121
- multipleSigners.encode(state, m.multipleSigners)
129
+ const flags = c.uint.decode(state)
130
+
131
+ return {
132
+ version: 0,
133
+ hash,
134
+ allowPatch: (flags & 1) !== 0,
135
+ quorum: c.uint.decode(state),
136
+ signers: signerArray.decode(state),
137
+ prologue: null
122
138
  }
139
+ }
140
+ }
141
+
142
+ const manifest = exports.manifest = {
143
+ preencode (state, m) {
144
+ state.end++ // version
145
+ if (m.version === 0) return manifestv0.preencode(state, m)
146
+
147
+ state.end++ // flags
148
+ hashes.preencode(state, m.hash)
149
+
150
+ c.uint.preencode(state, m.quorum)
151
+ signerArray.preencode(state, m.signers)
152
+ if (m.prologue) prologue.preencode(state, m.prologue)
153
+ },
154
+ encode (state, m) {
155
+ c.uint.encode(state, m.version)
156
+ if (m.version === 0) return manifestv0.encode(state, m)
157
+
158
+ c.uint.encode(state, (m.allowPatch ? 1 : 0) | (m.prologue ? 2 : 0))
159
+ hashes.encode(state, m.hash)
160
+
161
+ c.uint.encode(state, m.quorum)
162
+ signerArray.encode(state, m.signers)
163
+ if (m.prologue) prologue.encode(state, m.prologue)
123
164
  },
124
165
  decode (state) {
125
- const version = c.uint.decode(state)
126
- if (version !== 0) throw new Error('Invalid version: ' + version)
166
+ const v = c.uint.decode(state)
167
+ if (v === 0) return manifestv0.decode(state)
168
+ if (v !== 1) throw new Error('Unknown version: ' + v)
127
169
 
170
+ const flags = c.uint.decode(state)
128
171
  const hash = hashes.decode(state)
129
- const type = c.uint.decode(state)
130
-
131
- if (type > 2) throw new Error('Unknown type: ' + type)
172
+ const quorum = c.uint.decode(state)
173
+ const signers = signerArray.decode(state)
132
174
 
133
175
  return {
176
+ version: 1,
134
177
  hash,
135
- static: type === 0 ? c.fixed32.decode(state) : null,
136
- signer: type === 1 ? signer.decode(state) : null,
137
- multipleSigners: type === 2 ? multipleSigners.decode(state) : null
178
+ allowPatch: (flags & 1) !== 0,
179
+ quorum,
180
+ signers,
181
+ prologue: (flags & 2) === 0 ? null : prologue.decode(state)
138
182
  }
139
183
  }
140
184
  }
@@ -831,14 +875,16 @@ oplog.header = {
831
875
  external: null,
832
876
  key: old.signer.publicKey,
833
877
  manifest: {
878
+ version: 0,
834
879
  hash: old.types.tree,
835
- static: null,
836
- signer: {
880
+ allowPatch: false,
881
+ quorum: 1,
882
+ signers: [{
837
883
  signature: old.types.signer,
838
884
  namespace: DEFAULT_NAMESPACE,
839
885
  publicKey: old.signer.publicKey
840
- },
841
- multipleSigners: null
886
+ }],
887
+ prologue: null
842
888
  },
843
889
  keyPair: old.signer.secretKey ? old.signer : null,
844
890
  userData: old.userData,
@@ -875,7 +921,27 @@ oplog.header = {
875
921
 
876
922
  const uintArray = c.array(c.uint)
877
923
 
878
- const patchEncoding = {
924
+ const multisigInput = {
925
+ preencode (state, inp) {
926
+ c.uint.preencode(state, inp.signer)
927
+ c.fixed64.preencode(state, inp.signature)
928
+ c.uint.preencode(state, inp.patch)
929
+ },
930
+ encode (state, inp) {
931
+ c.uint.encode(state, inp.signer)
932
+ c.fixed64.encode(state, inp.signature)
933
+ c.uint.encode(state, inp.patch)
934
+ },
935
+ decode (state) {
936
+ return {
937
+ signer: c.uint.decode(state),
938
+ signature: c.fixed64.decode(state),
939
+ patch: c.uint.decode(state)
940
+ }
941
+ }
942
+ }
943
+
944
+ const patchEncodingv0 = {
879
945
  preencode (state, n) {
880
946
  c.uint.preencode(state, n.start)
881
947
  c.uint.preencode(state, n.length)
@@ -895,29 +961,30 @@ const patchEncoding = {
895
961
  }
896
962
  }
897
963
 
898
- const multisigInput = {
964
+ const multisigInputv0 = {
899
965
  preencode (state, n) {
900
966
  state.end++
901
967
  c.uint.preencode(state, n.signer)
902
968
  c.fixed64.preencode(state, n.signature)
903
- if (n.patch) patchEncoding.preencode(state, n.patch)
969
+ if (n.patch) patchEncodingv0.preencode(state, n.patch)
904
970
  },
905
971
  encode (state, n) {
906
972
  c.uint.encode(state, n.patch ? 1 : 0)
907
973
  c.uint.encode(state, n.signer)
908
974
  c.fixed64.encode(state, n.signature)
909
- if (n.patch) patchEncoding.encode(state, n.patch)
975
+ if (n.patch) patchEncodingv0.encode(state, n.patch)
910
976
  },
911
977
  decode (state) {
912
978
  const flags = c.uint.decode(state)
913
979
  return {
914
980
  signer: c.uint.decode(state),
915
981
  signature: c.fixed64.decode(state),
916
- patch: (flags & 1) ? patchEncoding.decode(state) : null
982
+ patch: (flags & 1) ? patchEncodingv0.decode(state) : null
917
983
  }
918
984
  }
919
985
  }
920
986
 
987
+ const multisigInputArrayv0 = c.array(multisigInputv0)
921
988
  const multisigInputArray = c.array(multisigInput)
922
989
 
923
990
  const compactNode = {
@@ -942,19 +1009,36 @@ const compactNode = {
942
1009
 
943
1010
  const compactNodeArray = c.array(compactNode)
944
1011
 
1012
+ exports.multiSignaturev0 = {
1013
+ preencode (state, s) {
1014
+ multisigInputArrayv0.preencode(state, s.proofs)
1015
+ compactNodeArray.preencode(state, s.patch)
1016
+ },
1017
+ encode (state, s) {
1018
+ multisigInputArrayv0.encode(state, s.proofs)
1019
+ compactNodeArray.encode(state, s.patch)
1020
+ },
1021
+ decode (state) {
1022
+ return {
1023
+ proofs: multisigInputArrayv0.decode(state),
1024
+ patch: compactNodeArray.decode(state)
1025
+ }
1026
+ }
1027
+ }
1028
+
945
1029
  exports.multiSignature = {
946
1030
  preencode (state, s) {
947
1031
  multisigInputArray.preencode(state, s.proofs)
948
- compactNodeArray.preencode(state, s.nodes)
1032
+ compactNodeArray.preencode(state, s.patch)
949
1033
  },
950
1034
  encode (state, s) {
951
1035
  multisigInputArray.encode(state, s.proofs)
952
- compactNodeArray.encode(state, s.nodes)
1036
+ compactNodeArray.encode(state, s.patch)
953
1037
  },
954
1038
  decode (state) {
955
1039
  return {
956
1040
  proofs: multisigInputArray.decode(state),
957
- nodes: compactNodeArray.decode(state)
1041
+ patch: compactNodeArray.decode(state)
958
1042
  }
959
1043
  }
960
1044
  }
package/lib/multisig.js CHANGED
@@ -1,45 +1,42 @@
1
1
  const c = require('compact-encoding')
2
2
  const b4a = require('b4a')
3
- const encoding = require('./messages').multiSignature
3
+ const flat = require('flat-tree')
4
+ const { multiSignature, multiSignaturev0 } = require('./messages')
4
5
 
5
6
  module.exports = {
7
+ assemblev0,
6
8
  assemble,
9
+ inflatev0,
7
10
  inflate,
8
11
  partialSignature,
9
12
  signableLength
10
13
  }
11
14
 
12
- function inflate (data) {
13
- const compressedInputs = c.decode(encoding, data)
14
- const inputs = []
15
-
16
- for (const proof of compressedInputs.proofs) {
17
- inputs.push({
18
- signer: proof.signer,
19
- signature: proof.signature,
20
- patch: inflateUpgrade(proof.patch, compressedInputs.nodes)
21
- })
22
- }
15
+ function inflatev0 (data) {
16
+ return c.decode(multiSignaturev0, data)
17
+ }
23
18
 
24
- return inputs
19
+ function inflate (data) {
20
+ return c.decode(multiSignature, data)
25
21
  }
26
22
 
27
23
  async function partialSignature (tree, signer, from, to = tree.length, signature = tree.signature) {
28
24
  if (from > tree.length) return null
29
- const patch = to <= from ? null : await upgrade(tree, from, to)
25
+ const nodes = to <= from ? null : await upgradeNodes(tree, from, to)
26
+
27
+ if (signature.byteLength !== 64) signature = c.decode(multiSignature, signature).proofs[0].signature
30
28
 
31
29
  return {
32
30
  signer,
33
31
  signature,
34
- patch
32
+ patch: nodes ? to - from : 0,
33
+ nodes
35
34
  }
36
35
  }
37
36
 
38
- async function upgrade (tree, from, to) {
37
+ async function upgradeNodes (tree, from, to) {
39
38
  const p = await tree.proof({ upgrade: { start: from, length: to - from } })
40
- p.upgrade.additionalNodes = []
41
- p.upgrade.signature = null
42
- return p.upgrade
39
+ return p.upgrade.nodes
43
40
  }
44
41
 
45
42
  function signableLength (lengths, quorum) {
@@ -53,15 +50,39 @@ function cmp (a, b) {
53
50
  return b - a
54
51
  }
55
52
 
53
+ function assemblev0 (inputs) {
54
+ const proofs = []
55
+ const patch = []
56
+
57
+ for (const u of inputs) {
58
+ proofs.push(compressProof(u, patch))
59
+ }
60
+
61
+ return c.encode(multiSignaturev0, { proofs, patch })
62
+ }
63
+
56
64
  function assemble (inputs) {
57
65
  const proofs = []
58
- const nodes = []
66
+ const patch = []
67
+ const seen = new Set()
59
68
 
60
69
  for (const u of inputs) {
61
- proofs.push(compressProof(u, nodes))
70
+ if (u.nodes) {
71
+ for (const node of u.nodes) {
72
+ if (seen.has(node.index)) continue
73
+ seen.add(node.index)
74
+ patch.push(node)
75
+ }
76
+ }
77
+
78
+ proofs.push({
79
+ signer: u.signer,
80
+ signature: u.signature,
81
+ patch: u.patch
82
+ })
62
83
  }
63
84
 
64
- return c.encode(encoding, { proofs, nodes })
85
+ return c.encode(multiSignature, { proofs, patch })
65
86
  }
66
87
 
67
88
  function compareNode (a, b) {
@@ -74,16 +95,14 @@ function compressProof (proof, nodes) {
74
95
  return {
75
96
  signer: proof.signer,
76
97
  signature: proof.signature,
77
- patch: compressUpgrade(proof.patch, nodes)
98
+ patch: proof.patch ? compressUpgrade(proof, nodes) : null
78
99
  }
79
100
  }
80
101
 
81
102
  function compressUpgrade (p, nodes) {
82
- if (!p) return null
83
-
84
103
  const u = {
85
- start: p.start,
86
- length: p.length,
104
+ start: flat.rightSpan(p.nodes[p.nodes.length - 1].index) / 2 + 1,
105
+ length: p.patch,
87
106
  nodes: []
88
107
  }
89
108
 
@@ -103,21 +122,3 @@ function compressUpgrade (p, nodes) {
103
122
 
104
123
  return u
105
124
  }
106
-
107
- function inflateUpgrade (s, nodes) {
108
- if (!s) return null
109
-
110
- const upgrade = {
111
- start: s.start,
112
- length: s.length,
113
- nodes: [],
114
- additionalNodes: [],
115
- signature: null
116
- }
117
-
118
- for (const i of s.nodes) {
119
- upgrade.nodes.push(nodes[i])
120
- }
121
-
122
- return upgrade
123
- }
package/lib/replicator.js CHANGED
@@ -7,6 +7,7 @@ const RemoteBitfield = require('./remote-bitfield')
7
7
  const { REQUEST_CANCELLED, REQUEST_TIMEOUT, INVALID_CAPABILITY, SNAPSHOT_NOT_AVAILABLE } = require('hypercore-errors')
8
8
  const m = require('./messages')
9
9
  const caps = require('./caps')
10
+ const { createTracer } = require('hypertrace')
10
11
 
11
12
  const DEFAULT_MAX_INFLIGHT = [32, 512]
12
13
  const SCALE_LATENCY = 50
@@ -268,6 +269,7 @@ class BlockTracker {
268
269
 
269
270
  class Peer {
270
271
  constructor (replicator, protomux, channel, session) {
272
+ this.tracer = createTracer(this, { parent: replicator.core.tracer })
271
273
  this.core = replicator.core
272
274
  this.replicator = replicator
273
275
  this.stream = protomux.stream
@@ -429,6 +431,8 @@ class Peer {
429
431
  }
430
432
 
431
433
  onclose (isRemote) {
434
+ this.tracer.trace('onclose')
435
+
432
436
  // we might have signalled to the remote that we are done (ie not downloading) and the remote might agree on that
433
437
  // if that happens, the channel might be closed by the remote. if so just renegotiate it.
434
438
  // TODO: add a CLOSE_REASON to mux to we can make this cleaner...
@@ -564,6 +568,8 @@ class Peer {
564
568
  }
565
569
 
566
570
  async onrequest (msg) {
571
+ this.tracer.trace('onrequest', msg)
572
+
567
573
  if (!this.protomux.drained || this.receiverQueue.length) {
568
574
  this.receiverQueue.push(msg)
569
575
  return
@@ -661,6 +667,8 @@ class Peer {
661
667
  }
662
668
 
663
669
  async ondata (data) {
670
+ this.tracer.trace('ondata', data)
671
+
664
672
  // always allow a fork conflict proof to be sent
665
673
  if (data.request === 0 && data.upgrade && data.upgrade.start === 0) {
666
674
  if (await this.core.checkConflict(data, this)) return
@@ -720,6 +728,8 @@ class Peer {
720
728
  }
721
729
 
722
730
  onnodata ({ request }) {
731
+ this.tracer.trace('onnodata', { request })
732
+
723
733
  const req = request > 0 ? this.replicator._inflight.get(request) : null
724
734
 
725
735
  if (req === null || req.peer !== this) return
@@ -1190,6 +1200,8 @@ class Peer {
1190
1200
  return
1191
1201
  }
1192
1202
 
1203
+ this.tracer.trace('send', req)
1204
+
1193
1205
  this.wireRequest.send(req)
1194
1206
  }
1195
1207
  }
@@ -1203,6 +1215,7 @@ module.exports = class Replicator {
1203
1215
  onupload = noop,
1204
1216
  oninvalid = noop
1205
1217
  } = {}) {
1218
+ this.tracer = createTracer(this)
1206
1219
  this.key = key
1207
1220
  this.discoveryKey = core.crypto.discoveryKey(key)
1208
1221
  this.core = core