envio 2.31.0-alpha.0 → 2.31.0-alpha.2

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.
@@ -40,188 +40,168 @@ type reorgResult = NoReorg | ReorgDetected(reorgDetected)
40
40
  type validBlockError = NotFound | AlreadyReorgedHashes
41
41
  type validBlockResult = result<blockDataWithTimestamp, validBlockError>
42
42
 
43
- module LastBlockScannedHashes: {
44
- type t
45
- /**Instantiat t with existing data*/
46
- let makeWithData: (
47
- array<blockData>,
48
- ~confirmedBlockThreshold: int,
49
- ~detectedReorgBlock: blockData=?,
50
- ) => t
51
-
52
- /**Instantiat empty t with no block data*/
53
- let empty: (~confirmedBlockThreshold: int) => t
54
-
55
- /** Registers a new reorg guard, prunes unneeded data, and returns the updated state.
56
- * Resets internal state if shouldRollbackOnReorg is false (detect-only mode)
57
- */
58
- let registerReorgGuard: (
59
- t,
60
- ~reorgGuard: reorgGuard,
61
- ~currentBlockHeight: int,
62
- ~shouldRollbackOnReorg: bool,
63
- ) => (t, reorgResult)
64
-
65
- /**
66
- Returns the latest block data which matches block number and hashes in the provided array
67
- If it doesn't exist in the reorg threshold it returns None or the latest scanned block outside of the reorg threshold
68
- */
69
- let getLatestValidScannedBlock: (
70
- t,
71
- ~blockNumbersAndHashes: array<blockDataWithTimestamp>,
72
- ~currentBlockHeight: int,
73
- ~skipReorgDuplicationCheck: bool=?,
74
- ) => validBlockResult
75
-
76
- let getThresholdBlockNumbers: (t, ~currentBlockHeight: int) => array<int>
77
-
78
- let rollbackToValidBlockNumber: (t, ~blockNumber: int) => t
79
- } = {
80
- type t = {
81
- // Number of blocks behind head, we want to keep track
82
- // as a threshold for reorgs. If for eg. this is 200,
83
- // it means we are accounting for reorgs up to 200 blocks
84
- // behind the head
85
- confirmedBlockThreshold: int,
86
- // A hash map of recent blockdata by block number to make comparison checks
87
- // for reorgs.
88
- dataByBlockNumber: dict<blockData>,
89
- // The latest block which detected a reorg
90
- // and should never be valid.
91
- // We keep track of this to avoid responses
92
- // with the stale data from other data-source instances.
93
- detectedReorgBlock: option<blockData>,
94
- }
43
+ type t = {
44
+ // Whether to rollback on reorg
45
+ // Even if it's disabled, we still track reorgs checkpoints in memory
46
+ // and log when we detect an unhandled reorg
47
+ shouldRollbackOnReorg: bool,
48
+ // Number of blocks behind head, we want to keep track
49
+ // as a threshold for reorgs. If for eg. this is 200,
50
+ // it means we are accounting for reorgs up to 200 blocks
51
+ // behind the head
52
+ maxReorgDepth: int,
53
+ // A hash map of recent blockdata by block number to make comparison checks
54
+ // for reorgs.
55
+ dataByBlockNumber: dict<blockData>,
56
+ // The latest block which detected a reorg
57
+ // and should never be valid.
58
+ // We keep track of this to avoid responses
59
+ // with the stale data from other data-source instances.
60
+ detectedReorgBlock: option<blockData>,
61
+ }
95
62
 
96
- let makeWithData = (blocks, ~confirmedBlockThreshold, ~detectedReorgBlock=?) => {
97
- let dataByBlockNumber = Js.Dict.empty()
63
+ let make = (
64
+ ~chainReorgCheckpoints: array<Internal.reorgCheckpoint>,
65
+ ~maxReorgDepth,
66
+ ~shouldRollbackOnReorg,
67
+ ~detectedReorgBlock=?,
68
+ ) => {
69
+ let dataByBlockNumber = Js.Dict.empty()
70
+
71
+ chainReorgCheckpoints->Belt.Array.forEach(block => {
72
+ dataByBlockNumber->Utils.Dict.setByInt(
73
+ block.blockNumber,
74
+ {
75
+ blockHash: block.blockHash,
76
+ blockNumber: block.blockNumber,
77
+ },
78
+ )
79
+ })
98
80
 
99
- blocks->Belt.Array.forEach(block => {
100
- dataByBlockNumber->Js.Dict.set(block.blockNumber->Js.Int.toString, block)
101
- })
81
+ {
82
+ shouldRollbackOnReorg,
83
+ maxReorgDepth,
84
+ dataByBlockNumber,
85
+ detectedReorgBlock,
86
+ }
87
+ }
102
88
 
103
- {
104
- confirmedBlockThreshold,
105
- dataByBlockNumber,
106
- detectedReorgBlock,
89
+ let getDataByBlockNumberCopyInThreshold = (
90
+ {dataByBlockNumber, maxReorgDepth}: t,
91
+ ~currentBlockHeight,
92
+ ) => {
93
+ // Js engine automatically orders numeric object keys
94
+ let ascBlockNumberKeys = dataByBlockNumber->Js.Dict.keys
95
+ let thresholdBlockNumber = currentBlockHeight - maxReorgDepth
96
+
97
+ let copy = Js.Dict.empty()
98
+
99
+ for idx in 0 to ascBlockNumberKeys->Array.length - 1 {
100
+ let blockNumberKey = ascBlockNumberKeys->Js.Array2.unsafe_get(idx)
101
+ let scannedBlock = dataByBlockNumber->Js.Dict.unsafeGet(blockNumberKey)
102
+ let isInReorgThreshold = scannedBlock.blockNumber >= thresholdBlockNumber
103
+ if isInReorgThreshold {
104
+ copy->Js.Dict.set(blockNumberKey, scannedBlock)
107
105
  }
108
106
  }
109
- //Instantiates empty LastBlockHashes
110
- let empty = (~confirmedBlockThreshold) => {
111
- confirmedBlockThreshold,
112
- dataByBlockNumber: Js.Dict.empty(),
113
- detectedReorgBlock: None,
114
- }
115
-
116
- let getDataByBlockNumberCopyInThreshold = (
117
- {dataByBlockNumber, confirmedBlockThreshold}: t,
118
- ~currentBlockHeight,
119
- ) => {
120
- // Js engine automatically orders numeric object keys
121
- let ascBlockNumberKeys = dataByBlockNumber->Js.Dict.keys
122
- let thresholdBlockNumber = currentBlockHeight - confirmedBlockThreshold
123
107
 
124
- let copy = Js.Dict.empty()
108
+ copy
109
+ }
125
110
 
126
- for idx in 0 to ascBlockNumberKeys->Array.length - 1 {
127
- let blockNumberKey = ascBlockNumberKeys->Js.Array2.unsafe_get(idx)
128
- let scannedBlock = dataByBlockNumber->Js.Dict.unsafeGet(blockNumberKey)
129
- let isInReorgThreshold = scannedBlock.blockNumber >= thresholdBlockNumber
130
- if isInReorgThreshold {
131
- copy->Js.Dict.set(blockNumberKey, scannedBlock)
111
+ /** Registers a new reorg guard, prunes unneeded data, and returns the updated state.
112
+ * Resets internal state if shouldRollbackOnReorg is false (detect-only mode)
113
+ */
114
+ let registerReorgGuard = (
115
+ {maxReorgDepth, shouldRollbackOnReorg} as self: t,
116
+ ~reorgGuard: reorgGuard,
117
+ ~currentBlockHeight,
118
+ ) => {
119
+ let dataByBlockNumberCopyInThreshold =
120
+ self->getDataByBlockNumberCopyInThreshold(~currentBlockHeight)
121
+
122
+ let {rangeLastBlock, prevRangeLastBlock} = reorgGuard
123
+
124
+ let maybeReorgDetected = switch dataByBlockNumberCopyInThreshold->Utils.Dict.dangerouslyGetNonOption(
125
+ rangeLastBlock.blockNumber->Int.toString,
126
+ ) {
127
+ | Some(scannedBlock) if scannedBlock.blockHash !== rangeLastBlock.blockHash =>
128
+ Some({
129
+ receivedBlock: rangeLastBlock,
130
+ scannedBlock,
131
+ })
132
+ | _ =>
133
+ switch prevRangeLastBlock {
134
+ //If parentHash is None, then it's the genesis block (no reorg)
135
+ //Need to check that parentHash matches because of the dynamic contracts
136
+ | None => None
137
+ | Some(prevRangeLastBlock) =>
138
+ switch dataByBlockNumberCopyInThreshold->Utils.Dict.dangerouslyGetNonOption(
139
+ prevRangeLastBlock.blockNumber->Int.toString,
140
+ ) {
141
+ | Some(scannedBlock) if scannedBlock.blockHash !== prevRangeLastBlock.blockHash =>
142
+ Some({
143
+ receivedBlock: prevRangeLastBlock,
144
+ scannedBlock,
145
+ })
146
+ | _ => None
132
147
  }
133
148
  }
134
-
135
- copy
136
149
  }
137
150
 
138
- let registerReorgGuard = (
139
- {confirmedBlockThreshold} as self: t,
140
- ~reorgGuard: reorgGuard,
141
- ~currentBlockHeight,
142
- ~shouldRollbackOnReorg,
143
- ) => {
144
- let dataByBlockNumberCopyInThreshold =
145
- self->getDataByBlockNumberCopyInThreshold(~currentBlockHeight)
146
-
147
- let {rangeLastBlock, prevRangeLastBlock} = reorgGuard
148
-
149
- let maybeReorgDetected = switch dataByBlockNumberCopyInThreshold->Utils.Dict.dangerouslyGetNonOption(
150
- rangeLastBlock.blockNumber->Int.toString,
151
- ) {
152
- | Some(scannedBlock) if scannedBlock.blockHash !== rangeLastBlock.blockHash =>
153
- Some({
154
- receivedBlock: rangeLastBlock,
155
- scannedBlock,
156
- })
157
- | _ =>
151
+ switch maybeReorgDetected {
152
+ | Some(reorgDetected) => (
153
+ shouldRollbackOnReorg
154
+ ? {
155
+ ...self,
156
+ detectedReorgBlock: Some(reorgDetected.scannedBlock),
157
+ }
158
+ : make(~chainReorgCheckpoints=[], ~maxReorgDepth, ~shouldRollbackOnReorg),
159
+ ReorgDetected(reorgDetected),
160
+ )
161
+ | None => {
162
+ dataByBlockNumberCopyInThreshold->Js.Dict.set(
163
+ rangeLastBlock.blockNumber->Int.toString,
164
+ rangeLastBlock,
165
+ )
158
166
  switch prevRangeLastBlock {
159
- //If parentHash is None, then it's the genesis block (no reorg)
160
- //Need to check that parentHash matches because of the dynamic contracts
161
- | None => None
167
+ | None => ()
162
168
  | Some(prevRangeLastBlock) =>
163
- switch dataByBlockNumberCopyInThreshold->Utils.Dict.dangerouslyGetNonOption(
169
+ dataByBlockNumberCopyInThreshold->Js.Dict.set(
164
170
  prevRangeLastBlock.blockNumber->Int.toString,
165
- ) {
166
- | Some(scannedBlock) if scannedBlock.blockHash !== prevRangeLastBlock.blockHash =>
167
- Some({
168
- receivedBlock: prevRangeLastBlock,
169
- scannedBlock,
170
- })
171
- | _ => None
172
- }
171
+ prevRangeLastBlock,
172
+ )
173
173
  }
174
- }
175
174
 
176
- switch maybeReorgDetected {
177
- | Some(reorgDetected) => (
178
- shouldRollbackOnReorg
179
- ? {
180
- ...self,
181
- detectedReorgBlock: Some(reorgDetected.scannedBlock),
182
- }
183
- : empty(~confirmedBlockThreshold),
184
- ReorgDetected(reorgDetected),
175
+ (
176
+ {
177
+ maxReorgDepth,
178
+ dataByBlockNumber: dataByBlockNumberCopyInThreshold,
179
+ detectedReorgBlock: None,
180
+ shouldRollbackOnReorg,
181
+ },
182
+ NoReorg,
185
183
  )
186
- | None => {
187
- dataByBlockNumberCopyInThreshold->Js.Dict.set(
188
- rangeLastBlock.blockNumber->Int.toString,
189
- rangeLastBlock,
190
- )
191
- switch prevRangeLastBlock {
192
- | None => ()
193
- | Some(prevRangeLastBlock) =>
194
- dataByBlockNumberCopyInThreshold->Js.Dict.set(
195
- prevRangeLastBlock.blockNumber->Int.toString,
196
- prevRangeLastBlock,
197
- )
198
- }
199
-
200
- (
201
- {
202
- confirmedBlockThreshold,
203
- dataByBlockNumber: dataByBlockNumberCopyInThreshold,
204
- detectedReorgBlock: None,
205
- },
206
- NoReorg,
207
- )
208
- }
209
184
  }
210
185
  }
186
+ }
211
187
 
212
- let getLatestValidScannedBlock = (
213
- self: t,
214
- ~blockNumbersAndHashes: array<blockDataWithTimestamp>,
215
- ~currentBlockHeight,
216
- ~skipReorgDuplicationCheck=false,
217
- ) => {
218
- let verifiedDataByBlockNumber = Js.Dict.empty()
219
- for idx in 0 to blockNumbersAndHashes->Array.length - 1 {
220
- let blockData = blockNumbersAndHashes->Array.getUnsafe(idx)
221
- verifiedDataByBlockNumber->Js.Dict.set(blockData.blockNumber->Int.toString, blockData)
222
- }
188
+ /**
189
+ Returns the latest block data which matches block number and hashes in the provided array
190
+ If it doesn't exist in the reorg threshold it returns None or the latest scanned block outside of the reorg threshold
191
+ */
192
+ let getLatestValidScannedBlock = (
193
+ self: t,
194
+ ~blockNumbersAndHashes: array<blockDataWithTimestamp>,
195
+ ~currentBlockHeight,
196
+ ~skipReorgDuplicationCheck=false,
197
+ ) => {
198
+ let verifiedDataByBlockNumber = Js.Dict.empty()
199
+ for idx in 0 to blockNumbersAndHashes->Array.length - 1 {
200
+ let blockData = blockNumbersAndHashes->Array.getUnsafe(idx)
201
+ verifiedDataByBlockNumber->Js.Dict.set(blockData.blockNumber->Int.toString, blockData)
202
+ }
223
203
 
224
- /*
204
+ /*
225
205
  Let's say we indexed block X with hash A.
226
206
  The next query we got the block X with hash B.
227
207
  We assume that the hash A is reorged since we received it earlier than B.
@@ -234,98 +214,105 @@ module LastBlockScannedHashes: {
234
214
  we can skip the reorg duplication check if we're sure that the block hashes query
235
215
  is not coming from a different instance. (let's say we tried several times)
236
216
  */
237
- let isAlreadyReorgedResponse = skipReorgDuplicationCheck
238
- ? false
239
- : switch self.detectedReorgBlock {
240
- | Some(detectedReorgBlock) =>
241
- switch verifiedDataByBlockNumber->Utils.Dict.dangerouslyGetNonOption(
242
- detectedReorgBlock.blockNumber->Int.toString,
243
- ) {
244
- | Some(verifiedBlockData) => verifiedBlockData.blockHash === detectedReorgBlock.blockHash
245
- | None => false
246
- }
217
+ let isAlreadyReorgedResponse = skipReorgDuplicationCheck
218
+ ? false
219
+ : switch self.detectedReorgBlock {
220
+ | Some(detectedReorgBlock) =>
221
+ switch verifiedDataByBlockNumber->Utils.Dict.dangerouslyGetNonOption(
222
+ detectedReorgBlock.blockNumber->Int.toString,
223
+ ) {
224
+ | Some(verifiedBlockData) => verifiedBlockData.blockHash === detectedReorgBlock.blockHash
247
225
  | None => false
248
226
  }
249
-
250
- if isAlreadyReorgedResponse {
251
- Error(AlreadyReorgedHashes)
252
- } else {
253
- let dataByBlockNumber = self->getDataByBlockNumberCopyInThreshold(~currentBlockHeight)
254
- // Js engine automatically orders numeric object keys
255
- let ascBlockNumberKeys = dataByBlockNumber->Js.Dict.keys
256
-
257
- let getPrevScannedBlock = idx =>
258
- switch ascBlockNumberKeys
259
- ->Belt.Array.get(idx - 1)
260
- ->Option.flatMap(key => {
261
- // We should already validate that the block number is verified at the point
262
- verifiedDataByBlockNumber->Utils.Dict.dangerouslyGetNonOption(key)
263
- }) {
264
- | Some(data) => Ok(data)
265
- | None => Error(NotFound)
266
- }
267
-
268
- let rec loop = idx => {
269
- switch ascBlockNumberKeys->Belt.Array.get(idx) {
270
- | Some(blockNumberKey) =>
271
- let scannedBlock = dataByBlockNumber->Js.Dict.unsafeGet(blockNumberKey)
272
- switch verifiedDataByBlockNumber->Utils.Dict.dangerouslyGetNonOption(blockNumberKey) {
273
- | None =>
274
- Js.Exn.raiseError(
275
- `Unexpected case. Couldn't find verified hash for block number ${blockNumberKey}`,
276
- )
277
- | Some(verifiedBlockData) if verifiedBlockData.blockHash === scannedBlock.blockHash =>
278
- loop(idx + 1)
279
- | Some(_) => getPrevScannedBlock(idx)
280
- }
281
- | None => getPrevScannedBlock(idx)
282
- }
227
+ | None => false
283
228
  }
284
- loop(0)
285
- }
286
- }
287
229
 
288
- /**
289
- Return a BlockNumbersAndHashes.t rolled back to where blockData is less
290
- than the provided blockNumber
291
- */
292
- let rollbackToValidBlockNumber = (
293
- {dataByBlockNumber, confirmedBlockThreshold}: t,
294
- ~blockNumber: int,
295
- ) => {
230
+ if isAlreadyReorgedResponse {
231
+ Error(AlreadyReorgedHashes)
232
+ } else {
233
+ let dataByBlockNumber = self->getDataByBlockNumberCopyInThreshold(~currentBlockHeight)
296
234
  // Js engine automatically orders numeric object keys
297
235
  let ascBlockNumberKeys = dataByBlockNumber->Js.Dict.keys
298
236
 
299
- let newDataByBlockNumber = Js.Dict.empty()
237
+ let getPrevScannedBlock = idx =>
238
+ switch ascBlockNumberKeys
239
+ ->Belt.Array.get(idx - 1)
240
+ ->Option.flatMap(key => {
241
+ // We should already validate that the block number is verified at the point
242
+ verifiedDataByBlockNumber->Utils.Dict.dangerouslyGetNonOption(key)
243
+ }) {
244
+ | Some(data) => Ok(data)
245
+ | None => Error(NotFound)
246
+ }
300
247
 
301
248
  let rec loop = idx => {
302
249
  switch ascBlockNumberKeys->Belt.Array.get(idx) {
303
- | Some(blockNumberKey) => {
304
- let scannedBlock = dataByBlockNumber->Js.Dict.unsafeGet(blockNumberKey)
305
- let shouldKeep = scannedBlock.blockNumber <= blockNumber
306
- if shouldKeep {
307
- newDataByBlockNumber->Js.Dict.set(blockNumberKey, scannedBlock)
308
- loop(idx + 1)
309
- } else {
310
- ()
311
- }
250
+ | Some(blockNumberKey) =>
251
+ let scannedBlock = dataByBlockNumber->Js.Dict.unsafeGet(blockNumberKey)
252
+ switch verifiedDataByBlockNumber->Utils.Dict.dangerouslyGetNonOption(blockNumberKey) {
253
+ | None =>
254
+ Js.Exn.raiseError(
255
+ `Unexpected case. Couldn't find verified hash for block number ${blockNumberKey}`,
256
+ )
257
+ | Some(verifiedBlockData) if verifiedBlockData.blockHash === scannedBlock.blockHash =>
258
+ loop(idx + 1)
259
+ | Some(_) => getPrevScannedBlock(idx)
312
260
  }
313
- | None => ()
261
+ | None => getPrevScannedBlock(idx)
314
262
  }
315
263
  }
316
264
  loop(0)
265
+ }
266
+ }
317
267
 
318
- {
319
- confirmedBlockThreshold,
320
- dataByBlockNumber: newDataByBlockNumber,
321
- detectedReorgBlock: None,
268
+ /**
269
+ Return a BlockNumbersAndHashes.t rolled back to where blockData is less
270
+ than the provided blockNumber
271
+ */
272
+ let rollbackToValidBlockNumber = (
273
+ {dataByBlockNumber, maxReorgDepth, shouldRollbackOnReorg}: t,
274
+ ~blockNumber: int,
275
+ ) => {
276
+ // Js engine automatically orders numeric object keys
277
+ let ascBlockNumberKeys = dataByBlockNumber->Js.Dict.keys
278
+
279
+ let newDataByBlockNumber = Js.Dict.empty()
280
+
281
+ let rec loop = idx => {
282
+ switch ascBlockNumberKeys->Belt.Array.get(idx) {
283
+ | Some(blockNumberKey) => {
284
+ let scannedBlock = dataByBlockNumber->Js.Dict.unsafeGet(blockNumberKey)
285
+ let shouldKeep = scannedBlock.blockNumber <= blockNumber
286
+ if shouldKeep {
287
+ newDataByBlockNumber->Js.Dict.set(blockNumberKey, scannedBlock)
288
+ loop(idx + 1)
289
+ } else {
290
+ ()
291
+ }
292
+ }
293
+ | None => ()
322
294
  }
323
295
  }
296
+ loop(0)
297
+
298
+ {
299
+ maxReorgDepth,
300
+ dataByBlockNumber: newDataByBlockNumber,
301
+ detectedReorgBlock: None,
302
+ shouldRollbackOnReorg,
303
+ }
304
+ }
324
305
 
325
- let getThresholdBlockNumbers = (self: t, ~currentBlockHeight) => {
326
- let dataByBlockNumberCopyInThreshold =
327
- self->getDataByBlockNumberCopyInThreshold(~currentBlockHeight)
306
+ let getThresholdBlockNumbers = (self: t, ~currentBlockHeight) => {
307
+ let dataByBlockNumberCopyInThreshold =
308
+ self->getDataByBlockNumberCopyInThreshold(~currentBlockHeight)
309
+
310
+ dataByBlockNumberCopyInThreshold->Js.Dict.values->Js.Array2.map(v => v.blockNumber)
311
+ }
328
312
 
329
- dataByBlockNumberCopyInThreshold->Js.Dict.values->Js.Array2.map(v => v.blockNumber)
313
+ let getHashByBlockNumber = (reorgDetection: t, ~blockNumber) => {
314
+ switch reorgDetection.dataByBlockNumber->Utils.Dict.dangerouslyGetByIntNonOption(blockNumber) {
315
+ | Some(v) => Js.Null.Value(v.blockHash)
316
+ | None => Js.Null.Null
330
317
  }
331
318
  }
@@ -18,30 +18,26 @@ function reorgDetectedToLogParams(reorgDetected, shouldRollbackOnReorg) {
18
18
  };
19
19
  }
20
20
 
21
- function makeWithData(blocks, confirmedBlockThreshold, detectedReorgBlock) {
21
+ function make(chainReorgCheckpoints, maxReorgDepth, shouldRollbackOnReorg, detectedReorgBlock) {
22
22
  var dataByBlockNumber = {};
23
- Belt_Array.forEach(blocks, (function (block) {
24
- dataByBlockNumber[block.blockNumber.toString()] = block;
23
+ Belt_Array.forEach(chainReorgCheckpoints, (function (block) {
24
+ dataByBlockNumber[block.block_number] = {
25
+ blockHash: block.block_hash,
26
+ blockNumber: block.block_number
27
+ };
25
28
  }));
26
29
  return {
27
- confirmedBlockThreshold: confirmedBlockThreshold,
30
+ shouldRollbackOnReorg: shouldRollbackOnReorg,
31
+ maxReorgDepth: maxReorgDepth,
28
32
  dataByBlockNumber: dataByBlockNumber,
29
33
  detectedReorgBlock: detectedReorgBlock
30
34
  };
31
35
  }
32
36
 
33
- function empty(confirmedBlockThreshold) {
34
- return {
35
- confirmedBlockThreshold: confirmedBlockThreshold,
36
- dataByBlockNumber: {},
37
- detectedReorgBlock: undefined
38
- };
39
- }
40
-
41
37
  function getDataByBlockNumberCopyInThreshold(param, currentBlockHeight) {
42
38
  var dataByBlockNumber = param.dataByBlockNumber;
43
39
  var ascBlockNumberKeys = Object.keys(dataByBlockNumber);
44
- var thresholdBlockNumber = currentBlockHeight - param.confirmedBlockThreshold | 0;
40
+ var thresholdBlockNumber = currentBlockHeight - param.maxReorgDepth | 0;
45
41
  var copy = {};
46
42
  for(var idx = 0 ,idx_finish = ascBlockNumberKeys.length; idx < idx_finish; ++idx){
47
43
  var blockNumberKey = ascBlockNumberKeys[idx];
@@ -55,8 +51,9 @@ function getDataByBlockNumberCopyInThreshold(param, currentBlockHeight) {
55
51
  return copy;
56
52
  }
57
53
 
58
- function registerReorgGuard(self, reorgGuard, currentBlockHeight, shouldRollbackOnReorg) {
59
- var confirmedBlockThreshold = self.confirmedBlockThreshold;
54
+ function registerReorgGuard(self, reorgGuard, currentBlockHeight) {
55
+ var maxReorgDepth = self.maxReorgDepth;
56
+ var shouldRollbackOnReorg = self.shouldRollbackOnReorg;
60
57
  var dataByBlockNumberCopyInThreshold = getDataByBlockNumberCopyInThreshold(self, currentBlockHeight);
61
58
  var prevRangeLastBlock = reorgGuard.prevRangeLastBlock;
62
59
  var rangeLastBlock = reorgGuard.rangeLastBlock;
@@ -85,10 +82,11 @@ function registerReorgGuard(self, reorgGuard, currentBlockHeight, shouldRollback
85
82
  if (maybeReorgDetected !== undefined) {
86
83
  return [
87
84
  shouldRollbackOnReorg ? ({
88
- confirmedBlockThreshold: self.confirmedBlockThreshold,
85
+ shouldRollbackOnReorg: self.shouldRollbackOnReorg,
86
+ maxReorgDepth: self.maxReorgDepth,
89
87
  dataByBlockNumber: self.dataByBlockNumber,
90
88
  detectedReorgBlock: maybeReorgDetected.scannedBlock
91
- }) : empty(confirmedBlockThreshold),
89
+ }) : make([], maxReorgDepth, shouldRollbackOnReorg, undefined),
92
90
  {
93
91
  TAG: "ReorgDetected",
94
92
  _0: maybeReorgDetected
@@ -101,7 +99,8 @@ function registerReorgGuard(self, reorgGuard, currentBlockHeight, shouldRollback
101
99
  }
102
100
  return [
103
101
  {
104
- confirmedBlockThreshold: confirmedBlockThreshold,
102
+ shouldRollbackOnReorg: shouldRollbackOnReorg,
103
+ maxReorgDepth: maxReorgDepth,
105
104
  dataByBlockNumber: dataByBlockNumberCopyInThreshold,
106
105
  detectedReorgBlock: undefined
107
106
  },
@@ -196,7 +195,8 @@ function rollbackToValidBlockNumber(param, blockNumber) {
196
195
  };
197
196
  loop(0);
198
197
  return {
199
- confirmedBlockThreshold: param.confirmedBlockThreshold,
198
+ shouldRollbackOnReorg: param.shouldRollbackOnReorg,
199
+ maxReorgDepth: param.maxReorgDepth,
200
200
  dataByBlockNumber: newDataByBlockNumber,
201
201
  detectedReorgBlock: undefined
202
202
  };
@@ -209,15 +209,21 @@ function getThresholdBlockNumbers(self, currentBlockHeight) {
209
209
  });
210
210
  }
211
211
 
212
- var LastBlockScannedHashes = {
213
- makeWithData: makeWithData,
214
- empty: empty,
215
- registerReorgGuard: registerReorgGuard,
216
- getLatestValidScannedBlock: getLatestValidScannedBlock,
217
- getThresholdBlockNumbers: getThresholdBlockNumbers,
218
- rollbackToValidBlockNumber: rollbackToValidBlockNumber
219
- };
212
+ function getHashByBlockNumber(reorgDetection, blockNumber) {
213
+ var v = reorgDetection.dataByBlockNumber[blockNumber];
214
+ if (v !== undefined) {
215
+ return v.blockHash;
216
+ } else {
217
+ return null;
218
+ }
219
+ }
220
220
 
221
221
  exports.reorgDetectedToLogParams = reorgDetectedToLogParams;
222
- exports.LastBlockScannedHashes = LastBlockScannedHashes;
222
+ exports.make = make;
223
+ exports.getDataByBlockNumberCopyInThreshold = getDataByBlockNumberCopyInThreshold;
224
+ exports.registerReorgGuard = registerReorgGuard;
225
+ exports.getLatestValidScannedBlock = getLatestValidScannedBlock;
226
+ exports.rollbackToValidBlockNumber = rollbackToValidBlockNumber;
227
+ exports.getThresholdBlockNumbers = getThresholdBlockNumbers;
228
+ exports.getHashByBlockNumber = getHashByBlockNumber;
223
229
  /* No side effect */