@bsv/wallet-toolbox 1.6.22 → 1.6.24
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/CHANGELOG.md +11 -0
- package/docs/client.md +300 -167
- package/docs/monitor.md +126 -23
- package/docs/services.md +86 -37
- package/docs/wallet.md +300 -167
- package/mobile/out/src/CWIStyleWalletManager.d.ts +1 -0
- package/mobile/out/src/CWIStyleWalletManager.d.ts.map +1 -1
- package/mobile/out/src/CWIStyleWalletManager.js +4 -2
- package/mobile/out/src/CWIStyleWalletManager.js.map +1 -1
- package/mobile/out/src/index.mobile.d.ts +1 -1
- package/mobile/out/src/index.mobile.js +1 -1
- package/mobile/out/src/monitor/Monitor.d.ts +32 -8
- package/mobile/out/src/monitor/Monitor.d.ts.map +1 -1
- package/mobile/out/src/monitor/Monitor.js +59 -28
- package/mobile/out/src/monitor/Monitor.js.map +1 -1
- package/mobile/out/src/monitor/tasks/TaskCheckNoSends.js +2 -1
- package/mobile/out/src/monitor/tasks/TaskCheckNoSends.js.map +1 -1
- package/mobile/out/src/monitor/tasks/TaskClock.js +3 -2
- package/mobile/out/src/monitor/tasks/TaskClock.js.map +1 -1
- package/mobile/out/src/monitor/tasks/TaskMonitorCallHistory.js +2 -1
- package/mobile/out/src/monitor/tasks/TaskMonitorCallHistory.js.map +1 -1
- package/mobile/out/src/monitor/tasks/TaskNewHeader.js +2 -1
- package/mobile/out/src/monitor/tasks/TaskNewHeader.js.map +1 -1
- package/mobile/out/src/monitor/tasks/TaskReorg.d.ts +47 -0
- package/mobile/out/src/monitor/tasks/TaskReorg.d.ts.map +1 -0
- package/mobile/out/src/monitor/tasks/TaskReorg.js +135 -0
- package/mobile/out/src/monitor/tasks/TaskReorg.js.map +1 -0
- package/mobile/out/src/monitor/tasks/TaskSendWaiting.js +2 -1
- package/mobile/out/src/monitor/tasks/TaskSendWaiting.js.map +1 -1
- package/mobile/out/src/monitor/tasks/TaskUnFail.js +2 -1
- package/mobile/out/src/monitor/tasks/TaskUnFail.js.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/Api/ChaintracksClientApi.d.ts +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/Api/ChaintracksClientApi.d.ts.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/Api/ChaintracksStorageApi.d.ts +4 -0
- package/mobile/out/src/services/chaintracker/chaintracks/Api/ChaintracksStorageApi.d.ts.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/Chaintracks.d.ts.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/Chaintracks.js +3 -1
- package/mobile/out/src/services/chaintracker/chaintracks/Chaintracks.js.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.d.ts.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.js +4 -1
- package/mobile/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.js.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.d.ts.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.js +3 -1
- package/mobile/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.js.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.d.ts +5 -0
- package/mobile/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.d.ts.map +1 -0
- package/mobile/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.js +68 -0
- package/mobile/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.js.map +1 -0
- package/mobile/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.d.ts +2 -1
- package/mobile/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.d.ts.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.js +59 -15
- package/mobile/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.js.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/createIdbChaintracks.d.ts +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/createIdbChaintracks.d.ts.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/createIdbChaintracks.js +4 -61
- package/mobile/out/src/services/chaintracker/chaintracks/createIdbChaintracks.js.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.d.ts +13 -0
- package/mobile/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.d.ts.map +1 -0
- package/mobile/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.js +27 -0
- package/mobile/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.js.map +1 -0
- package/mobile/out/src/services/chaintracker/chaintracks/index.client.d.ts +2 -28
- package/mobile/out/src/services/chaintracker/chaintracks/index.client.d.ts.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/index.client.js +2 -50
- package/mobile/out/src/services/chaintracker/chaintracks/index.client.js.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/index.mobile.d.ts +30 -0
- package/mobile/out/src/services/chaintracker/chaintracks/index.mobile.d.ts.map +1 -0
- package/mobile/out/src/services/chaintracker/chaintracks/index.mobile.js +68 -0
- package/mobile/out/src/services/chaintracker/chaintracks/index.mobile.js.map +1 -0
- package/mobile/out/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.js +11 -11
- package/mobile/out/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.js.map +1 -1
- package/mobile/out/src/storage/methods/createAction.d.ts.map +1 -1
- package/mobile/out/src/storage/methods/createAction.js.map +1 -1
- package/mobile/package-lock.json +7 -6
- package/mobile/package.json +2 -2
- package/out/src/CWIStyleWalletManager.d.ts +1 -0
- package/out/src/CWIStyleWalletManager.d.ts.map +1 -1
- package/out/src/CWIStyleWalletManager.js +4 -2
- package/out/src/CWIStyleWalletManager.js.map +1 -1
- package/out/src/index.mobile.d.ts +1 -1
- package/out/src/index.mobile.js +1 -1
- package/out/src/monitor/Monitor.d.ts +32 -8
- package/out/src/monitor/Monitor.d.ts.map +1 -1
- package/out/src/monitor/Monitor.js +59 -28
- package/out/src/monitor/Monitor.js.map +1 -1
- package/out/src/monitor/MonitorDaemon.d.ts +2 -0
- package/out/src/monitor/MonitorDaemon.d.ts.map +1 -1
- package/out/src/monitor/MonitorDaemon.js +3 -1
- package/out/src/monitor/MonitorDaemon.js.map +1 -1
- package/out/src/monitor/__test/MonitorDaemon.man.test.js +30 -39
- package/out/src/monitor/__test/MonitorDaemon.man.test.js.map +1 -1
- package/out/src/monitor/tasks/TaskCheckNoSends.js +2 -1
- package/out/src/monitor/tasks/TaskCheckNoSends.js.map +1 -1
- package/out/src/monitor/tasks/TaskClock.js +3 -2
- package/out/src/monitor/tasks/TaskClock.js.map +1 -1
- package/out/src/monitor/tasks/TaskMonitorCallHistory.js +2 -1
- package/out/src/monitor/tasks/TaskMonitorCallHistory.js.map +1 -1
- package/out/src/monitor/tasks/TaskNewHeader.js +2 -1
- package/out/src/monitor/tasks/TaskNewHeader.js.map +1 -1
- package/out/src/monitor/tasks/TaskReorg.d.ts +47 -0
- package/out/src/monitor/tasks/TaskReorg.d.ts.map +1 -0
- package/out/src/monitor/tasks/TaskReorg.js +135 -0
- package/out/src/monitor/tasks/TaskReorg.js.map +1 -0
- package/out/src/monitor/tasks/TaskSendWaiting.js +2 -1
- package/out/src/monitor/tasks/TaskSendWaiting.js.map +1 -1
- package/out/src/monitor/tasks/TaskUnFail.js +2 -1
- package/out/src/monitor/tasks/TaskUnFail.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Api/ChaintracksClientApi.d.ts +1 -1
- package/out/src/services/chaintracker/chaintracks/Api/ChaintracksClientApi.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Api/ChaintracksStorageApi.d.ts +4 -0
- package/out/src/services/chaintracker/chaintracks/Api/ChaintracksStorageApi.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Chaintracks.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Chaintracks.js +3 -1
- package/out/src/services/chaintracker/chaintracks/Chaintracks.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/ChaintracksService.js +1 -1
- package/out/src/services/chaintracker/chaintracks/ChaintracksService.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.js +4 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js +3 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.js +3 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/__tests/Chaintracks.test.js +1 -1
- package/out/src/services/chaintracker/chaintracks/__tests/Chaintracks.test.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.d.ts +5 -0
- package/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.d.ts.map +1 -0
- package/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.js +68 -0
- package/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.js.map +1 -0
- package/out/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.d.ts +2 -1
- package/out/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.js +66 -22
- package/out/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.d.ts +2 -1
- package/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.js +59 -15
- package/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createIdbChaintracks.d.ts +1 -1
- package/out/src/services/chaintracker/chaintracks/createIdbChaintracks.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createIdbChaintracks.js +4 -61
- package/out/src/services/chaintracker/chaintracks/createIdbChaintracks.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createKnexChaintracks.d.ts +14 -0
- package/out/src/services/chaintracker/chaintracks/createKnexChaintracks.d.ts.map +1 -0
- package/out/src/services/chaintracker/chaintracks/createKnexChaintracks.js +27 -0
- package/out/src/services/chaintracker/chaintracks/createKnexChaintracks.js.map +1 -0
- package/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.d.ts +13 -0
- package/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.d.ts.map +1 -0
- package/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.js +27 -0
- package/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.js.map +1 -0
- package/out/src/services/chaintracker/chaintracks/index.all.d.ts +1 -0
- package/out/src/services/chaintracker/chaintracks/index.all.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/index.all.js +1 -0
- package/out/src/services/chaintracker/chaintracks/index.all.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/index.client.d.ts +2 -28
- package/out/src/services/chaintracker/chaintracks/index.client.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/index.client.js +2 -50
- package/out/src/services/chaintracker/chaintracks/index.client.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/index.mobile.d.ts +30 -0
- package/out/src/services/chaintracker/chaintracks/index.mobile.d.ts.map +1 -0
- package/out/src/services/chaintracker/chaintracks/index.mobile.js +68 -0
- package/out/src/services/chaintracker/chaintracks/index.mobile.js.map +1 -0
- package/out/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.js +11 -11
- package/out/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.js.map +1 -1
- package/out/src/services/chaintracker/index.mobile.d.ts +4 -0
- package/out/src/services/chaintracker/index.mobile.d.ts.map +1 -0
- package/out/src/services/chaintracker/index.mobile.js +20 -0
- package/out/src/services/chaintracker/index.mobile.js.map +1 -0
- package/out/src/storage/methods/createAction.d.ts.map +1 -1
- package/out/src/storage/methods/createAction.js.map +1 -1
- package/out/src/storage/schema/KnexMigrations.d.ts.map +1 -1
- package/out/src/storage/schema/KnexMigrations.js +12 -0
- package/out/src/storage/schema/KnexMigrations.js.map +1 -1
- package/out/test/monitor/Monitor.test.js +32 -29
- package/out/test/monitor/Monitor.test.js.map +1 -1
- package/out/tsconfig.all.tsbuildinfo +1 -1
- package/package.json +5 -4
- package/src/CWIStyleWalletManager.ts +14 -4
- package/src/index.mobile.ts +1 -1
- package/src/monitor/Monitor.ts +94 -29
- package/src/monitor/MonitorDaemon.ts +9 -1
- package/src/monitor/__test/MonitorDaemon.man.test.ts +35 -7
- package/src/monitor/tasks/TaskCheckNoSends.ts +1 -1
- package/src/monitor/tasks/TaskClock.ts +2 -2
- package/src/monitor/tasks/TaskMonitorCallHistory.ts +1 -1
- package/src/monitor/tasks/TaskNewHeader.ts +1 -1
- package/src/monitor/tasks/TaskReorg.ts +139 -0
- package/src/monitor/tasks/TaskSendWaiting.ts +3 -3
- package/src/monitor/tasks/TaskUnFail.ts +1 -1
- package/src/services/chaintracker/chaintracks/Api/ChaintracksClientApi.ts +6 -1
- package/src/services/chaintracker/chaintracks/Api/ChaintracksStorageApi.ts +4 -0
- package/src/services/chaintracker/chaintracks/Chaintracks.ts +3 -1
- package/src/services/chaintracker/chaintracks/ChaintracksService.ts +2 -2
- package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.ts +4 -1
- package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.ts +4 -12
- package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.ts +3 -1
- package/src/services/chaintracker/chaintracks/__tests/Chaintracks.test.ts +2 -2
- package/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.ts +92 -0
- package/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.ts +84 -25
- package/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.ts +79 -17
- package/src/services/chaintracker/chaintracks/createIdbChaintracks.ts +11 -64
- package/src/services/chaintracker/chaintracks/createKnexChaintracks.ts +65 -0
- package/src/services/chaintracker/chaintracks/createNoDbChaintracks.ts +60 -0
- package/src/services/chaintracker/chaintracks/index.all.ts +1 -0
- package/src/services/chaintracker/chaintracks/index.client.ts +2 -35
- package/src/services/chaintracker/chaintracks/index.mobile.ts +37 -0
- package/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.ts +11 -11
- package/src/services/chaintracker/index.mobile.ts +4 -0
- package/src/storage/methods/createAction.ts +6 -1
- package/src/storage/schema/KnexMigrations.ts +13 -0
- package/syncVersions.js +71 -0
- package/test/monitor/Monitor.test.ts +21 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bsv/wallet-toolbox",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.24",
|
|
4
4
|
"description": "BRC100 conforming wallet, wallet storage and wallet signer components",
|
|
5
5
|
"main": "./out/src/index.js",
|
|
6
6
|
"types": "./out/src/index.d.ts",
|
|
@@ -22,8 +22,9 @@
|
|
|
22
22
|
"test:coverage": "npm run build && jest --testPathIgnorePatterns=man.test.ts --coverage",
|
|
23
23
|
"lint": "prettier --write 'src/**/*.ts' --write 'test/**/*.ts' --log-level silent",
|
|
24
24
|
"build": "tsc --build",
|
|
25
|
-
"prepublish": "npm run lint && npm run build && npm run doc",
|
|
26
|
-
"doc": "ts2md"
|
|
25
|
+
"prepublish": "npm run lint && npm run build && npm run doc && npm run sync-versions",
|
|
26
|
+
"doc": "ts2md",
|
|
27
|
+
"sync-versions": "node syncVersions.js"
|
|
27
28
|
},
|
|
28
29
|
"bugs": {
|
|
29
30
|
"url": "https://github.com/bsv-blockchain/wallet-toolbox/issues"
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
"dependencies": {
|
|
33
34
|
"@bsv/auth-express-middleware": "^1.2.3",
|
|
34
35
|
"@bsv/payment-express-middleware": "^1.2.3",
|
|
35
|
-
"@bsv/sdk": "^1.7.
|
|
36
|
+
"@bsv/sdk": "^1.7.6",
|
|
36
37
|
"express": "^4.21.2",
|
|
37
38
|
"idb": "^8.0.2",
|
|
38
39
|
"knex": "^3.1.0",
|
|
@@ -61,7 +61,9 @@ import {
|
|
|
61
61
|
Transaction,
|
|
62
62
|
PushDrop,
|
|
63
63
|
CreateActionInput,
|
|
64
|
-
SHIPBroadcaster
|
|
64
|
+
SHIPBroadcaster,
|
|
65
|
+
BigNumber,
|
|
66
|
+
Curve
|
|
65
67
|
} from '@bsv/sdk'
|
|
66
68
|
import { PrivilegedKeyManager } from './sdk/PrivilegedKeyManager'
|
|
67
69
|
|
|
@@ -1065,7 +1067,13 @@ export class CWIStyleWalletManager implements WalletInterface {
|
|
|
1065
1067
|
* Lists all available profiles, including the default profile.
|
|
1066
1068
|
* @returns Array of profile info objects, including an 'active' flag.
|
|
1067
1069
|
*/
|
|
1068
|
-
listProfiles(): Array<{
|
|
1070
|
+
listProfiles(): Array<{
|
|
1071
|
+
id: number[]
|
|
1072
|
+
name: string
|
|
1073
|
+
createdAt: number | null
|
|
1074
|
+
active: boolean
|
|
1075
|
+
identityKey: string
|
|
1076
|
+
}> {
|
|
1069
1077
|
if (!this.authenticated) {
|
|
1070
1078
|
throw new Error('Not authenticated.')
|
|
1071
1079
|
}
|
|
@@ -1075,14 +1083,16 @@ export class CWIStyleWalletManager implements WalletInterface {
|
|
|
1075
1083
|
id: DEFAULT_PROFILE_ID,
|
|
1076
1084
|
name: 'default',
|
|
1077
1085
|
createdAt: null, // Default profile doesn't have a creation timestamp in the same way
|
|
1078
|
-
active: this.activeProfileId.every(x => x === 0)
|
|
1086
|
+
active: this.activeProfileId.every(x => x === 0),
|
|
1087
|
+
identityKey: new PrivateKey(this.rootPrimaryKey).toPublicKey().toString()
|
|
1079
1088
|
},
|
|
1080
1089
|
// Other profiles
|
|
1081
1090
|
...this.profiles.map(p => ({
|
|
1082
1091
|
id: p.id,
|
|
1083
1092
|
name: p.name,
|
|
1084
1093
|
createdAt: p.createdAt,
|
|
1085
|
-
active: this.activeProfileId.every((x, i) => x === p.id[i])
|
|
1094
|
+
active: this.activeProfileId.every((x, i) => x === p.id[i]),
|
|
1095
|
+
identityKey: new PrivateKey(this.XOR(this.rootPrimaryKey as number[], p.primaryPad)).toPublicKey().toString()
|
|
1086
1096
|
}))
|
|
1087
1097
|
]
|
|
1088
1098
|
return profileList
|
package/src/index.mobile.ts
CHANGED
|
@@ -2,7 +2,7 @@ export * as sdk from './sdk/index'
|
|
|
2
2
|
|
|
3
3
|
export * from './utility/index.client'
|
|
4
4
|
export * from './storage/index.mobile'
|
|
5
|
-
export * from './services/chaintracker/chaintracks/index.
|
|
5
|
+
export * from './services/chaintracker/chaintracks/index.mobile'
|
|
6
6
|
|
|
7
7
|
export * from './CWIStyleWalletManager'
|
|
8
8
|
export * from './monitor/Monitor'
|
package/src/monitor/Monitor.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { TaskCheckForProofs } from './tasks/TaskCheckForProofs'
|
|
|
11
11
|
import { TaskClock } from './tasks/TaskClock'
|
|
12
12
|
import { TaskNewHeader } from './tasks/TaskNewHeader'
|
|
13
13
|
import { TaskMonitorCallHistory } from './tasks/TaskMonitorCallHistory'
|
|
14
|
+
import { TaskReorg } from './tasks/TaskReorg'
|
|
14
15
|
|
|
15
16
|
import { TaskSendWaiting } from './tasks/TaskSendWaiting'
|
|
16
17
|
import { TaskCheckNoSends } from './tasks/TaskCheckNoSends'
|
|
@@ -21,7 +22,8 @@ import { WERR_BAD_REQUEST, WERR_INVALID_PARAMETER } from '../sdk/WERR_errors'
|
|
|
21
22
|
import { WalletError } from '../sdk/WalletError'
|
|
22
23
|
import { BlockHeader } from '../sdk/WalletServices.interfaces'
|
|
23
24
|
import { Services } from '../services/Services'
|
|
24
|
-
import { ChaintracksClientApi } from '../services/chaintracker/chaintracks/Api/ChaintracksClientApi'
|
|
25
|
+
import { ChaintracksClientApi, ReorgListener } from '../services/chaintracker/chaintracks/Api/ChaintracksClientApi'
|
|
26
|
+
import { Chaintracks } from '../services/chaintracker/chaintracks/Chaintracks'
|
|
25
27
|
|
|
26
28
|
export type MonitorStorage = WalletStorageManager
|
|
27
29
|
|
|
@@ -34,6 +36,8 @@ export interface MonitorOptions {
|
|
|
34
36
|
|
|
35
37
|
chaintracks: ChaintracksClientApi
|
|
36
38
|
|
|
39
|
+
chaintracksWithEvents?: Chaintracks
|
|
40
|
+
|
|
37
41
|
/**
|
|
38
42
|
* How many msecs to wait after each getMerkleProof service request.
|
|
39
43
|
*/
|
|
@@ -59,7 +63,12 @@ export interface MonitorOptions {
|
|
|
59
63
|
* and potentially that reorgs update proofs that were already received.
|
|
60
64
|
*/
|
|
61
65
|
export class Monitor {
|
|
62
|
-
static createDefaultWalletMonitorOptions(
|
|
66
|
+
static createDefaultWalletMonitorOptions(
|
|
67
|
+
chain: Chain,
|
|
68
|
+
storage: MonitorStorage,
|
|
69
|
+
services?: Services,
|
|
70
|
+
chaintracks?: Chaintracks
|
|
71
|
+
): MonitorOptions {
|
|
63
72
|
services ||= new Services(chain)
|
|
64
73
|
if (!services.options.chaintracks) throw new WERR_INVALID_PARAMETER('services.options.chaintracks', 'valid')
|
|
65
74
|
const o: MonitorOptions = {
|
|
@@ -71,7 +80,8 @@ export class Monitor {
|
|
|
71
80
|
abandonedMsecs: 1000 * 60 * 5,
|
|
72
81
|
unprovenAttemptsLimitTest: 10,
|
|
73
82
|
unprovenAttemptsLimitMain: 144,
|
|
74
|
-
chaintracks: services.options.chaintracks
|
|
83
|
+
chaintracks: services.options.chaintracks,
|
|
84
|
+
chaintracksWithEvents: chaintracks
|
|
75
85
|
}
|
|
76
86
|
return o
|
|
77
87
|
}
|
|
@@ -81,6 +91,9 @@ export class Monitor {
|
|
|
81
91
|
chain: Chain
|
|
82
92
|
storage: MonitorStorage
|
|
83
93
|
chaintracks: ChaintracksClientApi
|
|
94
|
+
chaintracksWithEvents?: Chaintracks
|
|
95
|
+
reorgSubscriptionPromise?: Promise<string>
|
|
96
|
+
headersSubscriptionPromise?: Promise<string>
|
|
84
97
|
onTransactionBroadcasted?: (broadcastResult: ReviewActionResult) => Promise<void>
|
|
85
98
|
onTransactionProven?: (txStatus: ProvenTransactionStatus) => Promise<void>
|
|
86
99
|
|
|
@@ -90,15 +103,31 @@ export class Monitor {
|
|
|
90
103
|
this.chain = this.services.chain
|
|
91
104
|
this.storage = options.storage
|
|
92
105
|
this.chaintracks = options.chaintracks
|
|
106
|
+
this.chaintracksWithEvents = options.chaintracksWithEvents
|
|
93
107
|
this.onTransactionProven = options.onTransactionProven
|
|
94
108
|
this.onTransactionBroadcasted = options.onTransactionBroadcasted
|
|
109
|
+
|
|
110
|
+
if (this.chaintracksWithEvents) {
|
|
111
|
+
const c = this.chaintracksWithEvents
|
|
112
|
+
this.reorgSubscriptionPromise = c.subscribeReorgs(this.processReorg.bind(this))
|
|
113
|
+
this.headersSubscriptionPromise = c.subscribeHeaders(this.processHeader.bind(this))
|
|
114
|
+
}
|
|
95
115
|
}
|
|
96
116
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
117
|
+
async destroy(): Promise<void> {
|
|
118
|
+
if (this.chaintracksWithEvents) {
|
|
119
|
+
const c = this.chaintracksWithEvents
|
|
120
|
+
if (this.reorgSubscriptionPromise) await c.unsubscribe(await this.reorgSubscriptionPromise)
|
|
121
|
+
if (this.headersSubscriptionPromise) await c.unsubscribe(await this.headersSubscriptionPromise)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
static readonly oneSecond = 1000
|
|
126
|
+
static readonly oneMinute = 60 * Monitor.oneSecond
|
|
127
|
+
static readonly oneHour = 60 * Monitor.oneMinute
|
|
128
|
+
static readonly oneDay = 24 * Monitor.oneHour
|
|
129
|
+
static readonly oneWeek = 7 * Monitor.oneDay
|
|
130
|
+
|
|
102
131
|
/**
|
|
103
132
|
* _tasks are typically run by the scheduler but may also be run by runTask.
|
|
104
133
|
*/
|
|
@@ -113,9 +142,9 @@ export class Monitor {
|
|
|
113
142
|
purgeSpent: false,
|
|
114
143
|
purgeCompleted: false,
|
|
115
144
|
purgeFailed: true,
|
|
116
|
-
purgeSpentAge: 2 *
|
|
117
|
-
purgeCompletedAge: 2 *
|
|
118
|
-
purgeFailedAge: 5 *
|
|
145
|
+
purgeSpentAge: 2 * Monitor.oneWeek,
|
|
146
|
+
purgeCompletedAge: 2 * Monitor.oneWeek,
|
|
147
|
+
purgeFailedAge: 5 * Monitor.oneDay
|
|
119
148
|
}
|
|
120
149
|
|
|
121
150
|
addAllTasksToOther(): void {
|
|
@@ -129,6 +158,8 @@ export class Monitor {
|
|
|
129
158
|
this._otherTasks.push(new TaskCheckNoSends(this))
|
|
130
159
|
this._otherTasks.push(new TaskUnFail(this))
|
|
131
160
|
|
|
161
|
+
this._otherTasks.push(new TaskReorg(this))
|
|
162
|
+
|
|
132
163
|
this._otherTasks.push(new TaskFailAbandoned(this))
|
|
133
164
|
|
|
134
165
|
this._otherTasks.push(new TaskSyncWhenIdle(this))
|
|
@@ -141,13 +172,14 @@ export class Monitor {
|
|
|
141
172
|
this._tasks.push(new TaskClock(this))
|
|
142
173
|
this._tasks.push(new TaskNewHeader(this))
|
|
143
174
|
this._tasks.push(new TaskMonitorCallHistory(this))
|
|
144
|
-
this._tasks.push(new TaskSendWaiting(this, 8 *
|
|
145
|
-
this._tasks.push(new TaskCheckForProofs(this, 2 *
|
|
175
|
+
this._tasks.push(new TaskSendWaiting(this, 8 * Monitor.oneSecond, 7 * Monitor.oneSecond)) // Check every 8 seconds but must be 7 seconds old
|
|
176
|
+
this._tasks.push(new TaskCheckForProofs(this, 2 * Monitor.oneHour)) // Every two hours if no block found
|
|
146
177
|
this._tasks.push(new TaskCheckNoSends(this))
|
|
147
|
-
this._tasks.push(new TaskFailAbandoned(this, 8 *
|
|
178
|
+
this._tasks.push(new TaskFailAbandoned(this, 8 * Monitor.oneMinute))
|
|
148
179
|
this._tasks.push(new TaskUnFail(this))
|
|
149
|
-
//this._tasks.push(new TaskPurge(this, this.defaultPurgeParams, 6 *
|
|
180
|
+
//this._tasks.push(new TaskPurge(this, this.defaultPurgeParams, 6 * Monitor.oneHour))
|
|
150
181
|
this._tasks.push(new TaskReviewStatus(this))
|
|
182
|
+
this._tasks.push(new TaskReorg(this))
|
|
151
183
|
}
|
|
152
184
|
|
|
153
185
|
/**
|
|
@@ -158,13 +190,14 @@ export class Monitor {
|
|
|
158
190
|
this._tasks.push(new TaskClock(this))
|
|
159
191
|
this._tasks.push(new TaskNewHeader(this))
|
|
160
192
|
this._tasks.push(new TaskMonitorCallHistory(this))
|
|
161
|
-
this._tasks.push(new TaskSendWaiting(this, 8 *
|
|
162
|
-
this._tasks.push(new TaskCheckForProofs(this, 2 *
|
|
193
|
+
this._tasks.push(new TaskSendWaiting(this, 8 * Monitor.oneSecond, 7 * Monitor.oneSecond)) // Check every 8 seconds but must be 7 seconds old
|
|
194
|
+
this._tasks.push(new TaskCheckForProofs(this, 2 * Monitor.oneHour)) // Every two hours if no block found
|
|
163
195
|
this._tasks.push(new TaskCheckNoSends(this))
|
|
164
|
-
this._tasks.push(new TaskFailAbandoned(this, 8 *
|
|
196
|
+
this._tasks.push(new TaskFailAbandoned(this, 8 * Monitor.oneMinute))
|
|
165
197
|
this._tasks.push(new TaskUnFail(this))
|
|
166
|
-
//this._tasks.push(new TaskPurge(this, this.defaultPurgeParams, 6 *
|
|
198
|
+
//this._tasks.push(new TaskPurge(this, this.defaultPurgeParams, 6 * Monitor.oneHour))
|
|
167
199
|
this._tasks.push(new TaskReviewStatus(this))
|
|
200
|
+
this._tasks.push(new TaskReorg(this))
|
|
168
201
|
}
|
|
169
202
|
|
|
170
203
|
addTask(task: WalletMonitorTask): void {
|
|
@@ -177,14 +210,6 @@ export class Monitor {
|
|
|
177
210
|
this._tasks = this._tasks.filter(t => t.name !== name)
|
|
178
211
|
}
|
|
179
212
|
|
|
180
|
-
async setupChaintracksListeners(): Promise<void> {
|
|
181
|
-
try {
|
|
182
|
-
// TODO: Use a task monitoring the newest block headere to trigger processNewHeader and reorg handling.
|
|
183
|
-
} catch (err) {
|
|
184
|
-
/* this chaintracks doesn't support event subscriptions */
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
213
|
async runTask(name: string): Promise<string> {
|
|
189
214
|
let task = this._tasks.find(t => t.name === name)
|
|
190
215
|
let log = ''
|
|
@@ -248,17 +273,28 @@ export class Monitor {
|
|
|
248
273
|
}
|
|
249
274
|
|
|
250
275
|
_runAsyncSetup: boolean = true
|
|
276
|
+
_tasksRunningPromise?: PromiseLike<void>
|
|
277
|
+
resolveCompletion: ((value: void | PromiseLike<void>) => void) | undefined = undefined
|
|
251
278
|
|
|
252
279
|
async startTasks(): Promise<void> {
|
|
253
280
|
if (this._tasksRunning) throw new WERR_BAD_REQUEST('monitor tasks are already runnining.')
|
|
254
281
|
|
|
255
282
|
this._tasksRunning = true
|
|
283
|
+
this._tasksRunningPromise = new Promise(resolve => {
|
|
284
|
+
this.resolveCompletion = resolve
|
|
285
|
+
})
|
|
286
|
+
|
|
256
287
|
for (; this._tasksRunning; ) {
|
|
257
288
|
await this.runOnce()
|
|
258
289
|
|
|
259
290
|
// console.log(`${new Date().toISOString()} tasks run, waiting...`)
|
|
260
291
|
await wait(this.options.taskRunWaitMsecs)
|
|
261
292
|
}
|
|
293
|
+
|
|
294
|
+
if (this.resolveCompletion) {
|
|
295
|
+
this.resolveCompletion()
|
|
296
|
+
this.resolveCompletion = undefined
|
|
297
|
+
}
|
|
262
298
|
}
|
|
263
299
|
|
|
264
300
|
async logEvent(event: string, details?: string): Promise<void> {
|
|
@@ -322,6 +358,8 @@ export class Monitor {
|
|
|
322
358
|
}
|
|
323
359
|
}
|
|
324
360
|
|
|
361
|
+
deactivatedHeaders: DeactivedHeader[] = []
|
|
362
|
+
|
|
325
363
|
/**
|
|
326
364
|
* Process reorg event received from Chaintracks
|
|
327
365
|
*
|
|
@@ -333,7 +371,34 @@ export class Monitor {
|
|
|
333
371
|
* Coinbase transactions always become invalid.
|
|
334
372
|
*/
|
|
335
373
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
336
|
-
processReorg(depth: number, oldTip: BlockHeader, newTip: BlockHeader): void {
|
|
337
|
-
|
|
374
|
+
processReorg(depth: number, oldTip: BlockHeader, newTip: BlockHeader, deactivatedHeaders?: BlockHeader[]): void {
|
|
375
|
+
if (deactivatedHeaders) {
|
|
376
|
+
for (const header of deactivatedHeaders) {
|
|
377
|
+
this.deactivatedHeaders.push({
|
|
378
|
+
whenMsecs: Date.now(),
|
|
379
|
+
tries: 0,
|
|
380
|
+
header
|
|
381
|
+
})
|
|
382
|
+
}
|
|
383
|
+
}
|
|
338
384
|
}
|
|
385
|
+
|
|
386
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
387
|
+
processHeader(header: BlockHeader): void {}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
export interface DeactivedHeader {
|
|
391
|
+
/**
|
|
392
|
+
* To control aging of notification before pursuing updated proof data.
|
|
393
|
+
*/
|
|
394
|
+
whenMsecs: number
|
|
395
|
+
/**
|
|
396
|
+
* Number of attempts made to process the header.
|
|
397
|
+
* Supports returning deactivation notification to the queue if proof data is not yet available.
|
|
398
|
+
*/
|
|
399
|
+
tries: number
|
|
400
|
+
/**
|
|
401
|
+
* The deactivated block header.
|
|
402
|
+
*/
|
|
403
|
+
header: BlockHeader
|
|
339
404
|
}
|
|
@@ -11,6 +11,7 @@ import { Monitor } from './Monitor'
|
|
|
11
11
|
import { WERR_INTERNAL, WERR_INVALID_PARAMETER } from '../sdk/WERR_errors'
|
|
12
12
|
import { wait } from '../utility/utilityHelpers'
|
|
13
13
|
import { WalletError } from '../sdk/WalletError'
|
|
14
|
+
import { Chaintracks } from '../services/chaintracker/chaintracks/Chaintracks'
|
|
14
15
|
dotenv.config()
|
|
15
16
|
|
|
16
17
|
const mainDojoConnection = process.env.MAIN_DOJO_CONNECTION || ''
|
|
@@ -28,6 +29,7 @@ export interface MonitorDaemonSetup {
|
|
|
28
29
|
servicesOptions?: WalletServicesOptions
|
|
29
30
|
services?: Services
|
|
30
31
|
monitor?: Monitor
|
|
32
|
+
chaintracks?: Chaintracks
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
export class MonitorDaemon {
|
|
@@ -99,6 +101,7 @@ export class MonitorDaemon {
|
|
|
99
101
|
if (a.servicesOptions) {
|
|
100
102
|
if (a.servicesOptions.chain != a.chain)
|
|
101
103
|
throw new WERR_INVALID_PARAMETER('serviceOptions.chain', 'same as args.chain')
|
|
104
|
+
a.servicesOptions.chaintracks ||= a.chaintracks
|
|
102
105
|
a.services = new Services(a.servicesOptions)
|
|
103
106
|
}
|
|
104
107
|
|
|
@@ -108,7 +111,12 @@ export class MonitorDaemon {
|
|
|
108
111
|
|
|
109
112
|
a.storageManager.setServices(a.services)
|
|
110
113
|
|
|
111
|
-
const monitorOptions = Monitor.createDefaultWalletMonitorOptions(
|
|
114
|
+
const monitorOptions = Monitor.createDefaultWalletMonitorOptions(
|
|
115
|
+
a.chain,
|
|
116
|
+
a.storageManager,
|
|
117
|
+
a.services,
|
|
118
|
+
a.chaintracks
|
|
119
|
+
)
|
|
112
120
|
a.monitor = new Monitor(monitorOptions)
|
|
113
121
|
}
|
|
114
122
|
|
|
@@ -1,17 +1,45 @@
|
|
|
1
|
-
import * as dotenv from 'dotenv'
|
|
2
1
|
import { MonitorDaemon } from '../MonitorDaemon'
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import { Chain } from '../../sdk/types'
|
|
3
|
+
import { Services } from '../../services/Services'
|
|
4
|
+
import { _tu } from '../../../test/utils/TestUtilsWalletStorage'
|
|
5
|
+
import { createDefaultNoDbChaintracksOptions } from '../../services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions'
|
|
6
|
+
import { Chaintracks } from '../../services/chaintracker/chaintracks/Chaintracks'
|
|
6
7
|
|
|
7
8
|
describe('MonitorDaemon tests', () => {
|
|
8
9
|
jest.setTimeout(99999999)
|
|
9
10
|
|
|
10
|
-
test('0', async () => {
|
|
11
|
+
test('0 mainnet', async () => {
|
|
12
|
+
await test0Body('main')
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
test('0a testnet', async () => {
|
|
16
|
+
await test0Body('test')
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
async function test0Body(chain: Chain) {
|
|
20
|
+
const env = _tu.getEnv(chain)
|
|
21
|
+
|
|
22
|
+
const servicesOptions = Services.createDefaultOptions(chain)
|
|
23
|
+
if (env.taalApiKey) {
|
|
24
|
+
servicesOptions.taalApiKey = env.taalApiKey
|
|
25
|
+
servicesOptions.arcConfig.apiKey = env.taalApiKey
|
|
26
|
+
}
|
|
27
|
+
if (env.whatsonchainApiKey) servicesOptions.whatsOnChainApiKey = env.whatsonchainApiKey
|
|
28
|
+
if (env.bitailsApiKey) servicesOptions.bitailsApiKey = env.bitailsApiKey
|
|
29
|
+
|
|
30
|
+
const u = undefined
|
|
31
|
+
const maxRetained = 32
|
|
32
|
+
const chaintracksOptions = createDefaultNoDbChaintracksOptions(chain, env.whatsonchainApiKey, u, maxRetained)
|
|
33
|
+
const chaintracks = new Chaintracks(chaintracksOptions)
|
|
34
|
+
servicesOptions.chaintracks = chaintracks
|
|
35
|
+
|
|
11
36
|
const d = new MonitorDaemon({
|
|
12
37
|
chain: 'test',
|
|
13
|
-
mySQLConnection: cloudMySQLConnection
|
|
38
|
+
mySQLConnection: env.cloudMySQLConnection,
|
|
39
|
+
servicesOptions,
|
|
40
|
+
chaintracks
|
|
14
41
|
})
|
|
42
|
+
|
|
15
43
|
await d.runDaemon()
|
|
16
|
-
}
|
|
44
|
+
}
|
|
17
45
|
})
|
|
@@ -7,7 +7,7 @@ export class TaskClock extends WalletMonitorTask {
|
|
|
7
7
|
|
|
8
8
|
constructor(
|
|
9
9
|
monitor: Monitor,
|
|
10
|
-
public triggerMsecs = 1 *
|
|
10
|
+
public triggerMsecs = 1 * Monitor.oneSecond
|
|
11
11
|
) {
|
|
12
12
|
super(monitor, TaskClock.taskName)
|
|
13
13
|
this.nextMinute = this.getNextMinute()
|
|
@@ -28,6 +28,6 @@ export class TaskClock extends WalletMonitorTask {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
getNextMinute(): number {
|
|
31
|
-
return Math.ceil(Date.now() /
|
|
31
|
+
return Math.ceil(Date.now() / Monitor.oneMinute) * Monitor.oneMinute
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { TableProvenTx } from '../../index.client'
|
|
2
|
+
import { BlockHeader } from '../../services/chaintracker/chaintracks/Api/BlockHeaderApi'
|
|
3
|
+
import { DeactivedHeader, Monitor } from '../Monitor'
|
|
4
|
+
import { WalletMonitorTask } from './WalletMonitorTask'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Check the `monitor.deactivatedHeaders` for any headers that have been deactivated.
|
|
8
|
+
*
|
|
9
|
+
* When headers are found, review matching ProvenTx records and update proof data as appropriate.
|
|
10
|
+
*
|
|
11
|
+
* New deactivated headers are pushed onto the `deactivatedHeaders` array.
|
|
12
|
+
* They must be shifted out as they are processed.
|
|
13
|
+
*
|
|
14
|
+
* The current implementation ages deactivation notifications by 10 minutes with each retry.
|
|
15
|
+
* If a successful proof update confirms original proof data after 3 retries, the original is retained.
|
|
16
|
+
*
|
|
17
|
+
* In normal operation there should never be any work for this task to perform.
|
|
18
|
+
* The most common result is that there are no matching proven_txs records because
|
|
19
|
+
* generating new proven_txs records intentionally lags new block generation to
|
|
20
|
+
* minimize this disruption.
|
|
21
|
+
*
|
|
22
|
+
* It is very disruptive to update a proven_txs record because:
|
|
23
|
+
* - Sync'ed storage is impacted.
|
|
24
|
+
* - Generated beefs are impacted.
|
|
25
|
+
* - Updated proof data may be unavailable at the time a reorg is first reported.
|
|
26
|
+
*
|
|
27
|
+
* Instead of reorg notification derived from new header notification, reorg repair to
|
|
28
|
+
* the proven_txs table is more effectively driven by noticing that a beef generated for a new
|
|
29
|
+
* createAction fails to verify against the chaintracker.
|
|
30
|
+
*
|
|
31
|
+
* An alternate approach to processing these events is to revert the proven_txs record to a proven_tx_reqs record.
|
|
32
|
+
* Pros:
|
|
33
|
+
* - The same multiple attempt logic that already exists is reused.
|
|
34
|
+
* - Failing to obtain a new proof already has transaction failure handling in place.
|
|
35
|
+
* - Generated beefs automatically become one generation deeper, potentially allowing transaction outputs to be spent.
|
|
36
|
+
* Cons:
|
|
37
|
+
* - Transactions must revert to un-proven / un-mined.
|
|
38
|
+
*/
|
|
39
|
+
export class TaskReorg extends WalletMonitorTask {
|
|
40
|
+
static taskName = 'Reorg'
|
|
41
|
+
|
|
42
|
+
process: DeactivedHeader[] = []
|
|
43
|
+
|
|
44
|
+
constructor(
|
|
45
|
+
monitor: Monitor,
|
|
46
|
+
public agedMsecs = Monitor.oneMinute * 10,
|
|
47
|
+
public maxRetries = 3
|
|
48
|
+
) {
|
|
49
|
+
super(monitor, TaskReorg.taskName)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
trigger(nowMsecsSinceEpoch: number): { run: boolean } {
|
|
53
|
+
const cutoff = nowMsecsSinceEpoch - this.agedMsecs
|
|
54
|
+
const q = this.monitor.deactivatedHeaders
|
|
55
|
+
while (q.length > 0 && cutoff > q[0].whenMsecs) {
|
|
56
|
+
// Prepare to process deactivated headers that have aged sufficiently (agedMsecs)
|
|
57
|
+
const header = q.shift()!
|
|
58
|
+
this.process.push(header)
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
run: this.process.length > 0
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async runTask(): Promise<string> {
|
|
66
|
+
let log = ''
|
|
67
|
+
|
|
68
|
+
for (;;) {
|
|
69
|
+
const header = this.process.shift()
|
|
70
|
+
if (!header) break
|
|
71
|
+
|
|
72
|
+
let ptxs: TableProvenTx[] = []
|
|
73
|
+
|
|
74
|
+
await this.storage.runAsStorageProvider(async sp => {
|
|
75
|
+
// Lookup all the proven_txs records matching the deactivated headers
|
|
76
|
+
ptxs = await sp.findProvenTxs({ partial: { blockHash: header.header.hash } })
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
log += ` block ${header.header.hash} orphaned with ${ptxs.length} impacted transactions\n`
|
|
80
|
+
|
|
81
|
+
let retry = false
|
|
82
|
+
for (const ptx of ptxs) {
|
|
83
|
+
const mpr = await this.monitor.services.getMerklePath(ptx.txid)
|
|
84
|
+
if (mpr.merklePath && mpr.header) {
|
|
85
|
+
const mp = mpr.merklePath
|
|
86
|
+
const h = mpr.header
|
|
87
|
+
const leaf = mp.path[0].find(leaf => leaf.txid === true && leaf.hash === ptx.txid)
|
|
88
|
+
if (leaf) {
|
|
89
|
+
const update: Partial<TableProvenTx> = {
|
|
90
|
+
height: mp.blockHeight,
|
|
91
|
+
index: leaf.offset,
|
|
92
|
+
merklePath: mp.toBinary(),
|
|
93
|
+
merkleRoot: h.merkleRoot,
|
|
94
|
+
blockHash: h.hash
|
|
95
|
+
}
|
|
96
|
+
if (update.blockHash === ptx.blockHash) {
|
|
97
|
+
log += ` txid ${ptx.txid} merkle path update still based on deactivated header ${ptx.blockHash}\n`
|
|
98
|
+
if (header.tries + 1 >= this.maxRetries) {
|
|
99
|
+
log += ` maximum retries ${this.maxRetries} exceeded\n`
|
|
100
|
+
} else {
|
|
101
|
+
retry = true
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
// Verify the new proof's validity.
|
|
105
|
+
const merkleRoot = mp.computeRoot(ptx.txid)
|
|
106
|
+
const chaintracker = await this.monitor.services.getChainTracker()
|
|
107
|
+
const isValid = await chaintracker.isValidRootForHeight(merkleRoot, update.height!)
|
|
108
|
+
const logUpdate = ` height ${ptx.height} ${ptx.height === update.height ? 'unchanged' : `-> ${update.height}`}\n`
|
|
109
|
+
log += ` blockHash ${ptx.blockHash} -> ${update.blockHash}\n`
|
|
110
|
+
log += ` merkleRoot ${ptx.merkleRoot} -> ${update.merkleRoot}\n`
|
|
111
|
+
log += ` index ${ptx.index} -> ${update.index}\n`
|
|
112
|
+
if (!isValid) {
|
|
113
|
+
log +=
|
|
114
|
+
` txid ${ptx.txid} chaintracker fails to confirm updated merkle path update invalid\n` + logUpdate
|
|
115
|
+
} else {
|
|
116
|
+
await this.storage.runAsStorageProvider(async sp => {
|
|
117
|
+
await sp.updateProvenTx(ptx.provenTxId, update)
|
|
118
|
+
})
|
|
119
|
+
log += ` txid ${ptx.txid} proof data updated\n` + logUpdate
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
log += ` txid ${ptx.txid} merkle path update doesn't include txid\n`
|
|
124
|
+
retry = true
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
log += ` txid ${ptx.txid} merkle path update unavailable\n`
|
|
128
|
+
retry = true
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (retry) {
|
|
132
|
+
log += ` retrying...\n`
|
|
133
|
+
this.monitor.deactivatedHeaders.push({ header: header.header, whenMsecs: Date.now(), tries: header.tries + 1 })
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return log
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -16,9 +16,9 @@ export class TaskSendWaiting extends WalletMonitorTask {
|
|
|
16
16
|
|
|
17
17
|
constructor(
|
|
18
18
|
monitor: Monitor,
|
|
19
|
-
public triggerMsecs =
|
|
20
|
-
public agedMsecs =
|
|
21
|
-
public sendingMsecs =
|
|
19
|
+
public triggerMsecs = Monitor.oneSecond * 8,
|
|
20
|
+
public agedMsecs = Monitor.oneSecond * 7,
|
|
21
|
+
public sendingMsecs = Monitor.oneMinute * 5
|
|
22
22
|
) {
|
|
23
23
|
super(monitor, TaskSendWaiting.taskName)
|
|
24
24
|
}
|
|
@@ -10,7 +10,12 @@ export type HeaderListener = (header: BlockHeader) => void
|
|
|
10
10
|
/**
|
|
11
11
|
* @public
|
|
12
12
|
*/
|
|
13
|
-
export type ReorgListener = (
|
|
13
|
+
export type ReorgListener = (
|
|
14
|
+
depth: number,
|
|
15
|
+
oldTip: BlockHeader,
|
|
16
|
+
newTip: BlockHeader,
|
|
17
|
+
deactivatedHeaders?: BlockHeader[]
|
|
18
|
+
) => void
|
|
14
19
|
|
|
15
20
|
/**
|
|
16
21
|
* @public
|
|
@@ -256,6 +256,10 @@ export type InsertHeaderResult = {
|
|
|
256
256
|
* If `added` is true, this header was the active chain tip before the insert. It may or may not still be the active chain tip after the insert.
|
|
257
257
|
*/
|
|
258
258
|
priorTip: LiveBlockHeader | undefined
|
|
259
|
+
/**
|
|
260
|
+
* If a reorg has occurred, these headers where active and are now deactivated.
|
|
261
|
+
*/
|
|
262
|
+
deactivatedHeaders: LiveBlockHeader[]
|
|
259
263
|
/**
|
|
260
264
|
* header's previousHash was not found in database
|
|
261
265
|
*/
|
|
@@ -416,7 +416,9 @@ export class Chaintracks implements ChaintracksManagementApi {
|
|
|
416
416
|
const reorgListener = this.callbacks.reorg[id]
|
|
417
417
|
if (reorgListener) {
|
|
418
418
|
try {
|
|
419
|
-
|
|
419
|
+
const priorTip: BlockHeader = { ...ihr.priorTip }
|
|
420
|
+
const deactivated: BlockHeader[] = ihr.deactivatedHeaders.map(lbh => ({ ...lbh }))
|
|
421
|
+
reorgListener(ihr.reorgDepth, priorTip, header, deactivated)
|
|
420
422
|
} catch {
|
|
421
423
|
/* ignore all errors thrown */
|
|
422
424
|
}
|