Compare commits

...

128 Commits

Author SHA1 Message Date
semantic-release-bot bfe989e694 chore(release): 0.1.0-develop.23 [skip ci]
# [0.1.0-develop.23](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.22...v0.1.0-develop.23) (2023-11-18)
2023-11-18 14:22:21 +00:00
Derrick Hammer 8d500b0430
dep: update s5 module hash 2023-11-18 09:21:18 -05:00
semantic-release-bot 9fdc867b7e chore(release): 0.1.0-develop.22 [skip ci]
# [0.1.0-develop.22](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.21...v0.1.0-develop.22) (2023-10-15)

### Bug Fixes

* add resolvedDomain to Module type and use it instead in createModule so that the domain id stays consistent to the potential resolver version, when used as a callerDomain ([68642cc](68642ccb03))
2023-10-15 04:04:52 +00:00
Derrick Hammer 23fbdba303
Merge remote-tracking branch 'origin/develop' into develop 2023-10-15 00:03:41 -04:00
Derrick Hammer bc38395423
dep: update module hashes 2023-10-15 00:03:35 -04:00
Derrick Hammer 68642ccb03
fix: add resolvedDomain to Module type and use it instead in createModule so that the domain id stays consistent to the potential resolver version, when used as a callerDomain 2023-10-14 23:50:47 -04:00
Derrick Hammer 528c613858
dep: update peerDiscoveryRegistry hashes 2023-10-13 03:18:41 -04:00
semantic-release-bot 699706e80b chore(release): 0.1.0-develop.21 [skip ci]
# [0.1.0-develop.21](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.20...v0.1.0-develop.21) (2023-10-13)
2023-10-13 07:02:56 +00:00
Derrick Hammer 7896dce67f
Merge remote-tracking branch 'origin/develop' into develop 2023-10-13 03:01:39 -04:00
Derrick Hammer 647fdf1d3e
dep: update ircPeerDiscovery hashes 2023-10-13 03:01:35 -04:00
semantic-release-bot 9a6cb6fde0 chore(release): 0.1.0-develop.20 [skip ci]
# [0.1.0-develop.20](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.19...v0.1.0-develop.20) (2023-10-11)
2023-10-11 14:31:40 +00:00
Derrick Hammer 3a21924bd0
Merge remote-tracking branch 'origin/develop' into develop 2023-10-11 10:30:09 -04:00
Derrick Hammer dd7a688ca5
dep: update networkRegistry hashes 2023-10-11 10:30:03 -04:00
semantic-release-bot 3c3e238655 chore(release): 0.1.0-develop.19 [skip ci]
# [0.1.0-develop.19](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.18...v0.1.0-develop.19) (2023-09-20)

### Features

* change workers to use a dedicated iframe that for now is hosted. This should unlock a dedicated thread per worker and prevent cpu fighting ([cfeca11](cfeca11300))
2023-09-20 01:47:06 +00:00
Derrick Hammer 7d26cbda0c
Merge remote-tracking branch 'origin/develop' into develop 2023-09-19 21:45:35 -04:00
Derrick Hammer cfeca11300
feat: change workers to use a dedicated iframe that for now is hosted. This should unlock a dedicated thread per worker and prevent cpu fighting 2023-09-19 21:45:13 -04:00
Derrick Hammer 9bf9f386f7
dep: update s5 module hash 2023-09-19 21:43:34 -04:00
semantic-release-bot 94b44cc230 chore(release): 0.1.0-develop.18 [skip ci]
# [0.1.0-develop.18](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.17...v0.1.0-develop.18) (2023-09-16)

### Bug Fixes

* need to pass sw property back with responseNonce ([265d955](265d955795))
2023-09-16 18:42:14 +00:00
Derrick Hammer af3cb0bd76
Merge remote-tracking branch 'origin/develop' into develop 2023-09-16 14:41:08 -04:00
Derrick Hammer 265d955795
fix: need to pass sw property back with responseNonce 2023-09-16 14:40:59 -04:00
semantic-release-bot 2b45f68957 chore(release): 0.1.0-develop.17 [skip ci]
# [0.1.0-develop.17](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.16...v0.1.0-develop.17) (2023-09-13)

### Features

* add cached modules support with leveldb/indexeddb ([6e148c1](6e148c1e0a))
2023-09-13 00:37:53 +00:00
Derrick Hammer ec00928dc7
Merge remote-tracking branch 'origin/develop' into develop 2023-09-12 20:36:52 -04:00
Derrick Hammer 6e148c1e0a
feat: add cached modules support with leveldb/indexeddb 2023-09-12 20:36:47 -04:00
semantic-release-bot 1cbe17fe99 chore(release): 0.1.0-develop.16 [skip ci]
# [0.1.0-develop.16](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.15...v0.1.0-develop.16) (2023-09-11)

### Bug Fixes

* need to use query not event ([10eb4a9](10eb4a990e))
2023-09-11 19:08:28 +00:00
Derrick Hammer 5077b6c9ff
Merge remote-tracking branch 'origin/develop' into develop 2023-09-11 15:07:27 -04:00
Derrick Hammer 10eb4a990e
fix: need to use query not event 2023-09-11 15:02:33 -04:00
semantic-release-bot 2add443e4c chore(release): 0.1.0-develop.15 [skip ci]
# [0.1.0-develop.15](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.14...v0.1.0-develop.15) (2023-09-11)

### Bug Fixes

* pass the fullBytes of the hash, and return the CID in string form with fromRegistry ([2d61697](2d616979c3))
* use globalThis ([23c2848](23c2848683))
* use globalThis ([b6142a6](b6142a654d))

### Features

* add service worker support ([1524ff5](1524ff5c57))
2023-09-11 09:49:46 +00:00
Derrick Hammer d8d99120ca
Merge remote-tracking branch 'origin/develop' into develop 2023-09-11 05:48:42 -04:00
Derrick Hammer 1524ff5c57
feat: add service worker support 2023-09-11 05:48:33 -04:00
Derrick Hammer 45e6b6d390
dep: add networkRegistry hash 2023-09-11 05:47:57 -04:00
Derrick Hammer 94b32a988b
dep: update ircPeerDiscovery hash 2023-09-11 05:47:40 -04:00
Derrick Hammer 23c2848683
fix: use globalThis 2023-09-11 05:47:09 -04:00
Derrick Hammer bff17fb1e9
dep: update libkernel 2023-09-11 05:46:47 -04:00
Derrick Hammer d90c30676a
refactor: only check for swarm in networkReady 2023-09-11 05:46:31 -04:00
Derrick Hammer 4e13f44b66
dep: add networkRegistry to CORE_MODULES 2023-09-11 05:45:14 -04:00
Derrick Hammer 706a12c480
dep: update ircPeerDiscovery resolver hash 2023-09-11 05:44:57 -04:00
Derrick Hammer 2d616979c3
fix: pass the fullBytes of the hash, and return the CID in string form with fromRegistry 2023-09-11 05:44:29 -04:00
Derrick Hammer b6142a654d
fix: use globalThis 2023-09-11 05:42:29 -04:00
semantic-release-bot c9c275cb21 chore(release): 0.1.0-develop.14 [skip ci]
# [0.1.0-develop.14](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.13...v0.1.0-develop.14) (2023-09-08)
2023-09-08 17:28:23 +00:00
Derrick Hammer 15a43d239b
dep: update libkernel 2023-09-08 13:27:21 -04:00
Derrick Hammer 77f6b04d5a
Merge remote-tracking branch 'origin/develop' into develop 2023-09-08 13:16:10 -04:00
Derrick Hammer 6449579e0a
refactor: maybeInitDefaultPortals no longer uses ErrTuples 2023-09-08 13:16:01 -04:00
Derrick Hammer b7bfbcc3cf
refactor: use CID class 2023-09-08 13:15:33 -04:00
Derrick Hammer 75c6c30284
refactor: downloadSmallObject no longer uses ErrTuples 2023-09-08 13:15:15 -04:00
Derrick Hammer 3c8eb1b081
refactor: import objAsString from libkernel 2023-09-08 13:13:41 -04:00
Derrick Hammer a73561d369
refactor: use CID class 2023-09-08 13:13:18 -04:00
Derrick Hammer 9dcb711c35
dep: update libkernel 2023-09-08 13:06:26 -04:00
Derrick Hammer b7fcd9fede
dep: update libkernel 2023-09-08 08:54:40 -04:00
semantic-release-bot 52ae881d9c chore(release): 0.1.0-develop.13 [skip ci]
# [0.1.0-develop.13](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.12...v0.1.0-develop.13) (2023-09-04)
2023-09-04 11:46:57 +00:00
Derrick Hammer 254283e679
Merge remote-tracking branch 'origin/develop' into develop 2023-09-04 07:45:36 -04:00
Derrick Hammer e06e00cd49
dep: update libkernel 2023-09-04 07:44:58 -04:00
semantic-release-bot ee072c1433 chore(release): 0.1.0-develop.12 [skip ci]
# [0.1.0-develop.12](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.11...v0.1.0-develop.12) (2023-09-04)
2023-09-04 09:42:27 +00:00
Derrick Hammer 28f9ff4438
Merge remote-tracking branch 'origin/develop' into develop 2023-09-04 05:41:15 -04:00
Derrick Hammer c7cec41a71
dep: update peerDiscoveryRegistry module cid 2023-09-04 05:41:10 -04:00
Derrick Hammer c68986789d
dep: update swarm module cid 2023-09-04 05:41:02 -04:00
semantic-release-bot 273600cd6f chore(release): 0.1.0-develop.11 [skip ci]
# [0.1.0-develop.11](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.10...v0.1.0-develop.11) (2023-09-04)
2023-09-04 08:44:58 +00:00
Derrick Hammer f7206b585f
Merge remote-tracking branch 'origin/develop' into develop 2023-09-04 04:43:39 -04:00
Derrick Hammer 1e3002abbf
dep: update s5 module cid 2023-09-04 04:43:30 -04:00
Derrick Hammer af263bbc39
refactor: add support for internal messages 2023-09-04 04:11:28 -04:00
Derrick Hammer 867544e1c9
refactor: rewrite resolveModuleRegistryEntry to use decodeRegistryCid, decodeRegistryValue, and encodeCid 2023-09-04 04:09:46 -04:00
Derrick Hammer c5eeab0ba6
dep: update libkernel 2023-09-04 04:09:09 -04:00
semantic-release-bot 864ebbddd8 chore(release): 0.1.0-develop.10 [skip ci]
# [0.1.0-develop.10](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.9...v0.1.0-develop.10) (2023-09-03)
2023-09-03 06:18:16 +00:00
Derrick Hammer 4b5eeb0fad
Merge remote-tracking branch 'origin/develop' into develop 2023-09-03 02:17:13 -04:00
Derrick Hammer 0efd953824
dep: update ircPeerDiscovery hash 2023-09-03 02:17:07 -04:00
semantic-release-bot 9ae777f739 chore(release): 0.1.0-develop.9 [skip ci]
# [0.1.0-develop.9](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.8...v0.1.0-develop.9) (2023-09-03)

### Bug Fixes

* finalModule needs to be moduleDomain ([6b0d43f](6b0d43fe9b))
* have resolveModuleRegistryEntry decode the cid and pass the pubkey ([e6318cd](e6318cdc38))
2023-09-03 05:02:42 +00:00
Derrick Hammer 5880c46643
Merge remote-tracking branch 'origin/develop' into develop 2023-09-03 01:01:26 -04:00
Derrick Hammer 2ca758f28c
dep: update module hashes 2023-09-03 01:01:18 -04:00
Derrick Hammer 6b83e4c5b4
dep: update resolver CID's 2023-09-03 01:01:11 -04:00
Derrick Hammer 6b0d43fe9b
fix: finalModule needs to be moduleDomain 2023-09-02 14:46:22 -04:00
Derrick Hammer e6318cdc38
fix: have resolveModuleRegistryEntry decode the cid and pass the pubkey 2023-09-02 14:46:06 -04:00
semantic-release-bot b7b7d84a9e chore(release): 0.1.0-develop.8 [skip ci]
# [0.1.0-develop.8](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.7...v0.1.0-develop.8) (2023-09-02)

### Bug Fixes

* missing return ([7d44208](7d44208132))
* need to call swarm not peerDiscoveryRegistry ([27ba637](27ba637ac2))
* use message.data not message.data.data ([4a73a27](4a73a2779d))
2023-09-02 17:09:43 +00:00
Derrick Hammer 39497a6391
Merge remote-tracking branch 'origin/develop' into develop 2023-09-02 13:08:41 -04:00
Derrick Hammer 7d44208132
fix: missing return 2023-09-02 13:08:36 -04:00
Derrick Hammer 1c4da69806
dep: update module hashes 2023-09-02 13:08:24 -04:00
Derrick Hammer 4a73a2779d
fix: use message.data not message.data.data 2023-09-02 13:08:06 -04:00
Derrick Hammer 27ba637ac2
fix: need to call swarm not peerDiscoveryRegistry 2023-09-02 13:07:43 -04:00
semantic-release-bot 92264d2573 chore(release): 0.1.0-develop.7 [skip ci]
# [0.1.0-develop.7](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.6...v0.1.0-develop.7) (2023-09-02)
2023-09-02 13:52:26 +00:00
Derrick Hammer 93f42c35a9
Merge remote-tracking branch 'origin/develop' into develop 2023-09-02 09:51:09 -04:00
Derrick Hammer 2061716c7f
dep: add registry module defaults 2023-09-02 09:50:48 -04:00
Derrick Hammer a3cc54d19a
dep: swarm cid is wrong 2023-09-02 09:49:59 -04:00
Derrick Hammer d79fb134ea
dep: update CORE_MODULES CID's 2023-09-02 09:42:09 -04:00
semantic-release-bot 08432f9221 chore(release): 0.1.0-develop.6 [skip ci]
# [0.1.0-develop.6](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.5...v0.1.0-develop.6) (2023-09-02)
2023-09-02 12:07:47 +00:00
Derrick Hammer 025a065933
Merge remote-tracking branch 'origin/develop' into develop 2023-09-02 08:06:27 -04:00
Derrick Hammer 985d1c2e8a
refactor: change module cid detection so that we support resolver cids instead of the raw pubkey 2023-09-02 08:06:21 -04:00
Derrick Hammer 075dab28c7
dep: update libkernel and remove s5 since it is a child dep now 2023-09-02 08:04:42 -04:00
semantic-release-bot 4cf87cc138 chore(release): 0.1.0-develop.5 [skip ci]
# [0.1.0-develop.5](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.4...v0.1.0-develop.5) (2023-09-01)

### Bug Fixes

* fix import ([787c7c6](787c7c6637))

### Features

* add initial fallback registry support ([5cc457d](5cc457d78b))
* add initial support to query the network for a registry entry for a module ([ba4c6dc](ba4c6dcb95))
2023-09-01 23:05:08 +00:00
Derrick Hammer 787c7c6637
fix: fix import 2023-09-01 19:04:07 -04:00
Derrick Hammer 841a13e849
Merge remote-tracking branch 'origin/develop' into develop 2023-09-01 18:59:15 -04:00
Derrick Hammer ba4c6dcb95
feat: add initial support to query the network for a registry entry for a module 2023-09-01 18:59:06 -04:00
Derrick Hammer 5cc457d78b
feat: add initial fallback registry support 2023-09-01 15:38:24 -04:00
semantic-release-bot 6e2e8721b2 chore(release): 0.1.0-develop.4 [skip ci]
# [0.1.0-develop.4](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.3...v0.1.0-develop.4) (2023-08-10)
2023-08-10 07:15:40 +00:00
Derrick Hammer 704f2089c1
Merge remote-tracking branch 'origin/develop' into develop 2023-08-10 03:14:37 -04:00
Derrick Hammer 1b654c9a60
refactor: switch to using downloadSmallObject 2023-08-10 03:12:10 -04:00
semantic-release-bot 6cc88c389c chore(release): 0.1.0-develop.3 [skip ci]
# [0.1.0-develop.3](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.2...v0.1.0-develop.3) (2023-08-10)
2023-08-10 06:55:09 +00:00
Derrick Hammer 87eebe7427
Merge remote-tracking branch 'origin/develop' into develop 2023-08-10 02:54:10 -04:00
Derrick Hammer 5a824ecffc
dep: update libkernel, simplify deps 2023-08-10 02:54:03 -04:00
semantic-release-bot d30e0c7c50 chore(release): 0.1.0-develop.2 [skip ci]
# [0.1.0-develop.2](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.1...v0.1.0-develop.2) (2023-07-20)

### Bug Fixes

* HACK, alias rootPrivateKey to rootKey temporarily ([3f5adbf](3f5adbfb11))
2023-07-20 16:36:24 +00:00
Derrick Hammer 8276ab83f8
Merge remote-tracking branch 'origin/develop' into develop 2023-07-20 12:35:09 -04:00
Derrick Hammer 3f5adbfb11
fix: HACK, alias rootPrivateKey to rootKey temporarily 2023-07-20 12:35:01 -04:00
semantic-release-bot 78746b45eb chore(release): 0.1.0-develop.1 [skip ci]
# [0.1.0-develop.1](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.0.1...v0.1.0-develop.1) (2023-07-18)

### Bug Fixes

* always launch worker inside of createModule ([7093494](7093494227))
* pass root key to module ([27830c1](27830c1397))
* update libweb ([e72075f](e72075f99a))
* update libweb ([4f507fe](4f507fe79e))
* update libweb ([b98ded6](b98ded63c8))
* update object data ([4408dae](4408dae8eb))

### Features

* initial version ([03f4083](03f4083674))
2023-07-18 21:44:25 +00:00
Derrick Hammer d912d7a848
ci: add repository to package.json 2023-07-18 17:42:09 -04:00
Derrick Hammer 3cc398c5f7
ci: add semantic-release script 2023-07-18 17:41:32 -04:00
Derrick Hammer 63fc62401b
refactor: split handleIncomingMessage to its own file, set activePortalMasterKey, call maybeInitDefaultPortals 2023-07-18 17:06:28 -04:00
Derrick Hammer fcca0e2cc2
dep: update deps 2023-07-18 17:04:38 -04:00
Derrick Hammer 4408dae8eb
fix: update object data 2023-07-18 10:44:39 -04:00
Derrick Hammer b914067e85
dep: update deps 2023-07-18 10:44:11 -04:00
Derrick Hammer 96c6eacf89
ci: add .presetterrc.json 2023-07-04 02:11:50 -04:00
Derrick Hammer 27830c1397
fix: pass root key to module 2023-07-04 02:09:30 -04:00
Derrick Hammer 7093494227
fix: always launch worker inside of createModule 2023-07-04 02:06:41 -04:00
Derrick Hammer 2671fa35a7
refactor: switch to using verifyCid to check if module is valid 2023-07-04 02:06:09 -04:00
Derrick Hammer dd27520a8e
ci: move to github actions 2023-07-04 02:04:50 -04:00
Derrick Hammer f2eb164ae5
chore: update LICENSE 2023-07-04 02:04:29 -04:00
Derrick Hammer 7d6a7bda47
refactor: update to new libraries/tooling 2023-07-02 12:04:47 -04:00
Derrick Hammer b287cc3aff
refactor: set active portals based on bootloaderPortals 2023-06-23 19:35:26 -04:00
Derrick Hammer e72075f99a
fix: update libweb 2023-06-23 19:34:47 -04:00
Derrick Hammer 4f507fe79e
fix: update libweb 2023-06-23 18:50:16 -04:00
Derrick Hammer 08e7ef098b
ci: update rollup plugin config 2023-06-23 18:49:58 -04:00
Derrick Hammer c8d7336a84
ci: add clean:rollup script 2023-06-23 18:34:45 -04:00
Derrick Hammer 3f1bd189d4
ci: add wasm rollup plugin 2023-06-23 07:56:45 -04:00
Derrick Hammer b98ded63c8
fix: update libweb 2023-06-23 07:44:08 -04:00
Derrick Hammer bc0bbac6dd
ci: update rollup config 2023-06-23 05:50:10 -04:00
Derrick Hammer 0f546cfda8
ci: syntax error 2023-06-23 05:18:04 -04:00
Derrick Hammer ea97e1a681
ci: set source dir 2023-06-23 05:16:44 -04:00
Derrick Hammer 65b911cdc4
ci: fix build script 2023-06-23 05:15:42 -04:00
Derrick Hammer 371bff2ef7
ci: add npm-shrinkwrap.json 2023-06-23 05:14:09 -04:00
Derrick Hammer 5102c3405d
chore: add credits 2023-06-23 05:13:20 -04:00
Derrick Hammer d1d7f90b02
ci: setup 2023-06-23 05:07:03 -04:00
Derrick Hammer 03f4083674
feat: initial version 2023-06-23 05:04:11 -04:00
18 changed files with 21153 additions and 1 deletions

13
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,13 @@
name: Build/Publish
on:
push:
branches:
- master
- develop
- develop-*
jobs:
main:
uses: lumeweb/github-node-deploy-workflow/.github/workflows/main.yml@master
secrets: inherit

8
.presetterrc.json Normal file
View File

@ -0,0 +1,8 @@
{
"preset": [
"@lumeweb/presetter-kernel-module-preset"
],
"config": {
"browser": true
}
}

126
CHANGELOG.md Normal file
View File

@ -0,0 +1,126 @@
# [0.1.0-develop.23](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.22...v0.1.0-develop.23) (2023-11-18)
# [0.1.0-develop.22](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.21...v0.1.0-develop.22) (2023-10-15)
### Bug Fixes
* add resolvedDomain to Module type and use it instead in createModule so that the domain id stays consistent to the potential resolver version, when used as a callerDomain ([68642cc](https://git.lumeweb.com/LumeWeb/kernel/commit/68642ccb03fafb27662f51905ad628e70198b826))
# [0.1.0-develop.21](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.20...v0.1.0-develop.21) (2023-10-13)
# [0.1.0-develop.20](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.19...v0.1.0-develop.20) (2023-10-11)
# [0.1.0-develop.19](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.18...v0.1.0-develop.19) (2023-09-20)
### Features
* change workers to use a dedicated iframe that for now is hosted. This should unlock a dedicated thread per worker and prevent cpu fighting ([cfeca11](https://git.lumeweb.com/LumeWeb/kernel/commit/cfeca113007e6d3c331ebed64bfbc300cb441f0a))
# [0.1.0-develop.18](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.17...v0.1.0-develop.18) (2023-09-16)
### Bug Fixes
* need to pass sw property back with responseNonce ([265d955](https://git.lumeweb.com/LumeWeb/kernel/commit/265d95579550757c7d7e9d4a9b23f6690dbd2c29))
# [0.1.0-develop.17](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.16...v0.1.0-develop.17) (2023-09-13)
### Features
* add cached modules support with leveldb/indexeddb ([6e148c1](https://git.lumeweb.com/LumeWeb/kernel/commit/6e148c1e0a761ac1b253074c150b61d356285560))
# [0.1.0-develop.16](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.15...v0.1.0-develop.16) (2023-09-11)
### Bug Fixes
* need to use query not event ([10eb4a9](https://git.lumeweb.com/LumeWeb/kernel/commit/10eb4a990e333b1ef5bed05b0fbb2908d432569b))
# [0.1.0-develop.15](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.14...v0.1.0-develop.15) (2023-09-11)
### Bug Fixes
* pass the fullBytes of the hash, and return the CID in string form with fromRegistry ([2d61697](https://git.lumeweb.com/LumeWeb/kernel/commit/2d616979c3249c7c0d9c3da1574ce9ca22352405))
* use globalThis ([23c2848](https://git.lumeweb.com/LumeWeb/kernel/commit/23c2848683ab6ce5c8e2b46c04f0b5f5ae7d3234))
* use globalThis ([b6142a6](https://git.lumeweb.com/LumeWeb/kernel/commit/b6142a654d3040baa18bfae7caa2f4db5aa458c0))
### Features
* add service worker support ([1524ff5](https://git.lumeweb.com/LumeWeb/kernel/commit/1524ff5c57df1b7e1c88df52c6c1c0d4851dfc15))
# [0.1.0-develop.14](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.13...v0.1.0-develop.14) (2023-09-08)
# [0.1.0-develop.13](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.12...v0.1.0-develop.13) (2023-09-04)
# [0.1.0-develop.12](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.11...v0.1.0-develop.12) (2023-09-04)
# [0.1.0-develop.11](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.10...v0.1.0-develop.11) (2023-09-04)
# [0.1.0-develop.10](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.9...v0.1.0-develop.10) (2023-09-03)
# [0.1.0-develop.9](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.8...v0.1.0-develop.9) (2023-09-03)
### Bug Fixes
* finalModule needs to be moduleDomain ([6b0d43f](https://git.lumeweb.com/LumeWeb/kernel/commit/6b0d43fe9b41150a768025d8d6b2edc7033e1607))
* have resolveModuleRegistryEntry decode the cid and pass the pubkey ([e6318cd](https://git.lumeweb.com/LumeWeb/kernel/commit/e6318cdc38b839de8c95d36c1f5276596b57bd83))
# [0.1.0-develop.8](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.7...v0.1.0-develop.8) (2023-09-02)
### Bug Fixes
* missing return ([7d44208](https://git.lumeweb.com/LumeWeb/kernel/commit/7d442081322aad0bab186fa57476ab15fc07e30c))
* need to call swarm not peerDiscoveryRegistry ([27ba637](https://git.lumeweb.com/LumeWeb/kernel/commit/27ba637ac224bcac76635bc8659d76d0472f342d))
* use message.data not message.data.data ([4a73a27](https://git.lumeweb.com/LumeWeb/kernel/commit/4a73a2779d3a8020f06f0d8d75c386abf66e15b1))
# [0.1.0-develop.7](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.6...v0.1.0-develop.7) (2023-09-02)
# [0.1.0-develop.6](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.5...v0.1.0-develop.6) (2023-09-02)
# [0.1.0-develop.5](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.4...v0.1.0-develop.5) (2023-09-01)
### Bug Fixes
* fix import ([787c7c6](https://git.lumeweb.com/LumeWeb/kernel/commit/787c7c6637f8291c4b2e9558f1d68ebabcb2e225))
### Features
* add initial fallback registry support ([5cc457d](https://git.lumeweb.com/LumeWeb/kernel/commit/5cc457d78b40541c1ecfa1d6a5c07274a7d48ab6))
* add initial support to query the network for a registry entry for a module ([ba4c6dc](https://git.lumeweb.com/LumeWeb/kernel/commit/ba4c6dcb9552eeb7cf4b87e31d2f878b1eb83198))
# [0.1.0-develop.4](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.3...v0.1.0-develop.4) (2023-08-10)
# [0.1.0-develop.3](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.2...v0.1.0-develop.3) (2023-08-10)
# [0.1.0-develop.2](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.1.0-develop.1...v0.1.0-develop.2) (2023-07-20)
### Bug Fixes
* HACK, alias rootPrivateKey to rootKey temporarily ([3f5adbf](https://git.lumeweb.com/LumeWeb/kernel/commit/3f5adbfb11e2d7f505db843ee277f30482165992))
# [0.1.0-develop.1](https://git.lumeweb.com/LumeWeb/kernel/compare/v0.0.1...v0.1.0-develop.1) (2023-07-18)
### Bug Fixes
* always launch worker inside of createModule ([7093494](https://git.lumeweb.com/LumeWeb/kernel/commit/70934942275b6c53c0723b3e88421f86378310e5))
* pass root key to module ([27830c1](https://git.lumeweb.com/LumeWeb/kernel/commit/27830c139759e99006d0e99b8ddb80413344664c))
* update libweb ([e72075f](https://git.lumeweb.com/LumeWeb/kernel/commit/e72075f99aa4da9c040aa0300bc11688f81c714d))
* update libweb ([4f507fe](https://git.lumeweb.com/LumeWeb/kernel/commit/4f507fe79eeadbb237ac43a0021b983e086ddaed))
* update libweb ([b98ded6](https://git.lumeweb.com/LumeWeb/kernel/commit/b98ded63c8260d46873f27098f898da2aa7c00a1))
* update object data ([4408dae](https://git.lumeweb.com/LumeWeb/kernel/commit/4408dae8eb4f1c431cd8c8028c00d4bade680a89))
### Features
* initial version ([03f4083](https://git.lumeweb.com/LumeWeb/kernel/commit/03f4083674e143316084a765e1b6091d5bbcad52))

View File

@ -1,6 +1,7 @@
MIT License
Copyright (c) <year> <copyright holders>
Copyright (c) 2023 Hammer Technologies LLC
Copyright (c) 2022 Skynet Labs
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@ -1,2 +1,3 @@
# kernel
Code is based on, and copies much of its work from https://github.com/SkynetLabs/skynet-kernel/tree/beta/kernel

19734
npm-shrinkwrap.json generated Normal file

File diff suppressed because it is too large Load Diff

24
package.json Normal file
View File

@ -0,0 +1,24 @@
{
"name": "@lumeweb/kernel",
"version": "0.1.0-develop.23",
"type": "module",
"repository": {
"type": "git",
"url": "gitea@git.lumeweb.com:LumeWeb/kernel.git"
},
"devDependencies": {
"@lumeweb/presetter-kernel-module-preset": "^0.1.0-develop.43",
"binconv": "^0.2.0",
"presetter": "*",
"semantic-release": "^21.0.5"
},
"readme": "ERROR: No README data found!",
"scripts": {
"prepare": "presetter bootstrap",
"build": "run build",
"semantic-release": "semantic-release"
},
"dependencies": {
"@lumeweb/libkernel": "0.1.0-develop.53"
}
}

36
src/err.ts Normal file
View File

@ -0,0 +1,36 @@
// notableErrors is a persistent list of errors that should be checked after
// testing. You should only add to this array in the event of an error that
// indicates a bug with the kernel.
import { OpenQueryResponse } from "./queries.js";
const notableErrors: string[] = [];
// respondErr will send an error response to the caller that closes out the
// query for the provided nonce. The extra inputs of 'messagePortal' and
// 'isWorker' are necessary to handle the fact that the MessageEvent you get
// from a worker message is different from the MessageEvent you get from a
// window message, and also from the fact that postMessage has different
// arguments depending on whether the messagePortal is a worker or a window.
function respondErr(
event: MessageEvent,
messagePortal: any,
isWorker: boolean,
isInternal: false | ((message: OpenQueryResponse) => void),
err: string,
) {
const message = {
nonce: event.data.nonce,
method: "response",
data: {},
err,
} as OpenQueryResponse;
if (isWorker) {
messagePortal.postMessage(message);
} else if (isInternal) {
isInternal(message);
} else {
messagePortal.postMessage(message, event.origin);
}
}
export { notableErrors, respondErr };

43
src/index.ts Normal file
View File

@ -0,0 +1,43 @@
import { logLargeObjects } from "./logLargeState.js";
import { log, logErr } from "./log.js";
import { KERNEL_DISTRO, KERNEL_VERSION } from "./version.js";
import {
maybeInitDefaultPortals,
setActivePortalMasterKey,
} from "@lumeweb/libweb";
import { Client } from "@lumeweb/libportal";
import { addContextToErr } from "@lumeweb/libkernel";
import { handleIncomingMessage } from "./message.js";
import { activeKey } from "./key.js";
declare global {
interface Window {
bootloaderPortals: Client[];
}
}
// Kick off the thread that will periodically log all of the large objects in
// the kernel, so that it's easier to check for memory leaks.
logLargeObjects();
// Write a log that declares the kernel version and distribution.
log("init", "Lume Web Kernel v" + KERNEL_VERSION + "-" + KERNEL_DISTRO);
/*
Try to load either our saved portal(s) or the default portal(s)
*/
setActivePortalMasterKey(activeKey);
let portalLoadErr = false;
try {
maybeInitDefaultPortals();
} catch (e) {
let err = addContextToErr(e, "unable to init portals");
logErr(err);
portalLoadErr = true;
}
if (!portalLoadErr) {
window.addEventListener("message", handleIncomingMessage);
}

5
src/key.ts Normal file
View File

@ -0,0 +1,5 @@
import { hexToBytes } from "@lumeweb/libweb";
export const activeKey = hexToBytes(
globalThis.localStorage.getItem("key") as string,
);

31
src/log.ts Normal file
View File

@ -0,0 +1,31 @@
import { objAsString } from "@lumeweb/libkernel";
// wLog is a wrapper for the log and logErr functions, to deduplicate code.
//
// TODO: Need to implement a tag system for the logging. We will use the
// dashboard to control logging messages and verbosity.
function wLog(isErr: boolean, tag: string, ...inputs: any) {
let message = "[lumeweb-kernel]\n" + tag;
for (let i = 0; i < inputs.length; i++) {
message += "\n";
message += objAsString(inputs[i]);
}
window.parent.postMessage(
{
method: "log",
data: {
isErr,
message,
},
},
"*",
);
}
function log(tag: string, ...inputs: any) {
wLog(false, tag, ...inputs);
}
function logErr(tag: string, ...inputs: any) {
wLog(true, tag, ...inputs);
}
export { log, logErr };

28
src/logLargeState.ts Normal file
View File

@ -0,0 +1,28 @@
import { notableErrors } from "./err.js";
import { log } from "./log.js";
import { modules, modulesLoading, queries } from "./queries.js";
// Set up a loop that will periodically log all of the large objects in the
// kernel, for the sake of making detection and debugging easier in the event
// of a
let waitTime = 30000;
function logLargeObjects() {
const queriesLenStr = Object.keys(queries).length.toString();
const modulesLenStr = Object.keys(modules).length.toString();
const modulesLoadingLenStr = Object.keys(modulesLoading).length.toString();
log(
"open queries :: open modules :: modules loading :: notable errors : " +
queriesLenStr +
" :: " +
modulesLenStr +
" :: " +
modulesLoadingLenStr +
" :: " +
notableErrors.length,
);
waitTime *= 1.25;
setTimeout(logLargeObjects, waitTime);
}
setTimeout(logLargeObjects, waitTime);
export { logLargeObjects };

117
src/message.ts Normal file
View File

@ -0,0 +1,117 @@
// Overwrite the handleIncomingMessage function that gets called at the end of the
// event handler, allowing us to support custom messages.
import { logErr } from "./log.js";
import { KERNEL_DISTRO, KERNEL_VERSION } from "./version.js";
import { notableErrors, respondErr } from "./err.js";
import { handleModuleCall, handleQueryUpdate } from "./queries.js";
export const handleIncomingMessage = function (event: any) {
// Ignore all messages from ourself.
if (event.source === window) {
return;
}
if (event.origin.endsWith(".module.kernel.lumeweb.com")) {
return;
}
// Input validation.
if (!("method" in event.data)) {
logErr("handleIncomingMessage", "kernel request is missing 'method' field");
return;
}
if (!("nonce" in event.data)) {
logErr(
"handleIncomingMessage",
"message sent to kernel with no nonce field",
event.data,
);
return;
}
// Establish a debugging handler that a developer can call to verify
// that round-trip communication has been correctly programmed between
// the kernel and the calling application.
//
// It was easier to inline the message than to abstract it.
if (event.data.method === "version") {
event.source.postMessage(
{
nonce: event.data.nonce,
method: "response",
err: null,
data: {
distribution: KERNEL_DISTRO,
version: KERNEL_VERSION,
},
},
event.origin,
);
return;
}
// Establish a debugging handler to return any noteworthy errors that the
// kernel has encountered. This is mainly intended to be used by the test
// suite.
if (event.data.method === "checkErrs") {
event.source.postMessage(
{
nonce: event.data.nonce,
method: "response",
err: null,
data: {
errs: notableErrors,
},
},
event.origin,
);
return;
}
// Establish handlers for the major kernel methods.
if (event.data.method === "moduleCall") {
// Check for a domain. If the message was sent by a browser
// extension, we trust the domain provided by the extension,
// otherwise we use the domain of the parent as the domain.
// This does mean that the kernel is trusting that the user has
// no malicious browser extensions, as we aren't checking for
// **which** extension is sending the message, we are only
// checking that the message is coming from a browser
// extension.
if (event.origin.startsWith("moz") && !("domain" in event.data)) {
logErr(
"moduleCall",
"caller is an extension, but no domain was provided",
);
respondErr(
event,
event.source,
false,
false,
"caller is an extension, but not domain was provided",
);
return;
}
let domain;
if (event.origin.startsWith("moz")) {
domain = event.data.domain;
} else {
domain = new URL(event.origin).hostname;
}
handleModuleCall(event, event.source, domain, false, false);
return;
}
if (event.data.method === "queryUpdate") {
handleQueryUpdate(event);
return;
}
// Unrecognized method, reject the query.
respondErr(
event,
event.source,
false,
false,
"unrecognized method: " + event.data.method,
);
};

61
src/modules.ts Normal file
View File

@ -0,0 +1,61 @@
import { internalModuleCall, modules } from "./queries.js";
import { CID, SignedRegistryEntry } from "@lumeweb/libs5";
import { Level } from "level";
let moduleStore: Level<string, Uint8Array>;
const CORE_MODULES = {
swarm: "zrjTDyEX8Mh2PdDdRj5YL2byFGrYe1ksczRwPaTRFaCGSMG",
peerDiscoveryRegistry: "zrjD6CEchDtSex5VHjzMNSAdkJpMNfCtbxSnftgtfvtnsdY",
ircPeerDiscovery: "zrjHTx8tSQFWnmZ9JzK7XmJirqJQi2WRBLYp3fASaL2AfBQ",
s5: "zrjLjKVByzt233rfcjWvTQXrMfGFa11oBLydPaUk7gwnC2d",
networkRegistry: "zrjTCwTcK5Vco1h7cdUQKzs6yzeqm7vC5u5Lo9y1uhTyxnv",
};
export async function networkReady() {
for (const module of [CORE_MODULES.swarm]) {
if (!moduleLoaded(module)) {
return false;
}
}
const resolvers = await internalModuleCall(CORE_MODULES.swarm, "getRelays");
return resolvers.length > 0;
}
function moduleLoaded(module: string) {
return module in modules;
}
export async function resolveModuleRegistryEntry(module: string) {
const cid = CID.decode(module);
const pubkey = cid.hash.fullBytes;
const signedEntry = (await internalModuleCall(
CORE_MODULES.s5,
"getRegistryEntry",
{ pubkey },
)) as SignedRegistryEntry;
return CID.fromRegistry(signedEntry.data).toString();
}
async function initStore() {
if (moduleStore) {
return;
}
const db = new Level<string, Uint8Array>("kernel-module-store");
await db.open();
moduleStore = db;
}
export async function store() {
if (!moduleStore) {
await initStore();
}
return moduleStore;
}

789
src/queries.ts Normal file
View File

@ -0,0 +1,789 @@
import { notableErrors, respondErr } from "./err.js";
import { log, logErr } from "./log.js";
import { activeKey } from "./key.js";
import { KERNEL_DISTRO, KERNEL_VERSION } from "./version.js";
import {
addContextToErr,
bufToB64,
encodeU64,
equalBytes,
Err,
objAsString,
sha512,
} from "@lumeweb/libkernel";
import { deriveChildKey, downloadSmallObject } from "@lumeweb/libweb";
import { CID, CID_TYPES } from "@lumeweb/libs5";
import type { moduleQuery, presentKeyData } from "@lumeweb/libkernel/module";
import { defer } from "@lumeweb/libkernel/module";
import { readableStreamToUint8Array } from "binconv";
import { getSavedRegistryEntry } from "./registry.js";
import {
networkReady,
resolveModuleRegistryEntry,
store as moduleStore,
} from "./modules.js";
import { blake3 } from "@noble/hashes/blake3";
import Worker from "./worker.js";
// WorkerLaunchFn is the type signature of the function that launches the
// worker to set up for processing a query.
type WorkerLaunchFn = () => Promise<[Worker, Err]>;
// modules is a hashmap that maps from a domain to the module that handles
// queries to that domain. It maintains the domain and URL of the module so
// that the worker doesn't need to be downloaded multiple times to keep
// launching queries.
//
// a new worker gets launched for every query.
interface Module {
domain: string;
resolvedDomain: string;
code: Uint8Array;
launchWorker: WorkerLaunchFn;
worker?: Worker;
}
// OpenQuery holds all of the information necessary for managing an open query.
interface OpenQuery {
isWorker: boolean;
isInternal: boolean;
internalHandler?: (message: OpenQueryResponse) => void;
domain: string;
source: any;
dest: Worker;
nonce: string;
origin: string;
sw?: boolean;
}
export interface OpenQueryResponse {
nonce: string;
method: string;
data: any;
err?: any;
sw?: boolean;
}
// Define the stateful variables for managing the modules. We track the set of
// queries that are in progress, the set of skapps that are known to the
// kernel, the set of modules that we've downloaded, and the set of modules
// that are actively being downloaded.
let queriesNonce = 0;
const queries = {} as { [module: string]: OpenQuery };
const modules = {} as any;
const modulesLoading = {} as any;
// Create a standard message handler for messages coming from workers.
//
// TODO: If the worker makes a mistake or has a bug that makes it seem
// unstable, we should create some sort of debug log that can be viewed from
// the kernel debug/control panel. We'll need to make sure the debug logs don't
// consume too much memory, and we'll need to terminate workers that are
// bugging out.
//
// TODO: Set up a ratelimiting system for modules making logs, we don't want
// modules to be able to pollute the kernel and cause instability by logging
// too much.
//
// TODO: Need to check that the postMessage call in respondErr isn't going to
// throw or cause issuse in the event that the worker who sent the message has
// been terminated.
//
// TODO: We probably need to have timeouts for queries, if a query doesn't send
// an update after a certain amount of time we drop it.
function handleWorkerMessage(event: MessageEvent, mod: Module, worker: Worker) {
// TODO: Use of respondErr here may not be correct, should only be using
// respondErr for functions that are expecting a response and aren't
// already part of a separate query. If they are part of a separate query
// we need to close that query out gracefully.
// Perform input verification for a worker message.
if (!("method" in event.data)) {
logErr("worker", mod.domain, "received worker message with no method");
respondErr(event, worker, true, false, "received message with no method");
return;
}
// Check whether this is a logging call.
if (event.data.method === "log") {
// Perform the input verification for logging.
if (!("data" in event.data)) {
logErr(
"worker",
mod.domain,
"received worker log message with no data field",
);
respondErr(
event,
worker,
true,
false,
"received log messsage with no data field",
);
return;
}
if (typeof event.data.data.message !== "string") {
logErr(
"worker",
mod.domain,
"worker log data.message is not of type 'string'",
);
respondErr(
event,
worker,
true,
false,
"received log messsage with no message field",
);
return;
}
if (event.data.data.isErr === undefined) {
event.data.data.isErr = false;
}
if (typeof event.data.data.isErr !== "boolean") {
logErr(
"worker",
mod.domain,
"worker log data.isErr is not of type 'boolean'",
);
respondErr(
event,
worker,
true,
false,
"received log messsage with invalid isErr field",
);
return;
}
// Send the log to the parent so that the log can be put in the
// console.
if (event.data.data.isErr === false) {
log("worker", "[" + mod.domain + "]", event.data.data.message);
} else {
logErr("worker", "[" + mod.domain + "]", event.data.data.message);
}
return;
}
// Check for a nonce - log is the only message from a worker that does not
// need a nonce.
if (!("nonce" in event.data)) {
event.data.nonce = "N/A";
logErr(
"worker",
mod.domain,
"worker sent a message with no nonce",
event.data,
);
respondErr(event, worker, true, false, "received message with no nonce");
return;
}
// Handle a version request.
if (event.data.method === "version") {
worker.postMessage({
nonce: event.data.nonce,
method: "response",
err: null,
data: {
distribution: KERNEL_DISTRO,
version: KERNEL_VERSION,
err: null,
},
});
return;
}
// Handle a call from the worker to another module.
if (event.data.method === "moduleCall") {
handleModuleCall(event, worker, mod.domain, true, false);
return;
}
// The only other methods allowed are the queryUpdate, responseUpdate,
// and response methods.
const isQueryUpdate = event.data.method === "queryUpdate";
const isResponseUpdate = event.data.method === "responseUpdate";
const isResponse = event.data.method === "response";
if (isQueryUpdate || isResponseUpdate || isResponse) {
handleModuleResponse(event, mod, worker);
return;
}
// We don't know what this message was.
logErr(
"worker",
mod.domain,
"received message from worker with unrecognized method",
);
}
// createModule will create a module from the provided worker code and domain.
// This call does not launch the worker, that should be done separately.
async function createModule(
workerCode: Uint8Array,
domain: string,
resolvedDomain: string,
): Promise<[Module | null, Err]> {
// Create the module object.
const mod: Module = {
domain,
resolvedDomain,
code: workerCode,
launchWorker: function (): Promise<[Worker, Err]> {
return launchWorker(mod);
},
};
// Start worker
const [worker, err] = await mod.launchWorker();
if (err !== null) {
return [{} as Module, addContextToErr(err, "unable to launch worker")];
}
mod.worker = worker;
return [mod, null];
}
// launchWorker will launch a worker and perform all the setup so that the
// worker is ready to receive a query.
async function launchWorker(mod: Module): Promise<[Worker, Err]> {
// Create and launch the worker.
let worker: Worker;
try {
worker = new Worker(mod.code, CID.decode(mod.resolvedDomain));
await worker.ready;
} catch (err: any) {
logErr("worker", mod.domain, "unable to create worker", mod.domain, err);
return [
{} as Worker,
addContextToErr(objAsString(err), "unable to create worker"),
];
}
// clean up memory, we don't need the code anymore
mod.code = new Uint8Array();
// Set the onmessage and onerror functions.
worker.onmessage = function (event: MessageEvent) {
handleWorkerMessage(event, mod, worker);
};
worker.onerror = function (event: ErrorEvent) {
const errStr =
objAsString(event.message) +
"\n" +
objAsString(event.error) +
"\n" +
objAsString(event);
logErr(
"worker",
mod.domain,
addContextToErr(errStr, "received onerror event"),
);
};
// Send the key to the module.
const path = "moduleKeyDerivation" + mod.domain;
const moduleKey = deriveChildKey(activeKey, path);
const msgData: presentKeyData = {
key: moduleKey,
rootPrivateKey: activeKey,
// @ts-ignore
rootKey: activeKey,
};
const msg: moduleQuery = {
method: "presentKey",
domain: "root",
data: msgData,
};
worker.postMessage(msg);
return [worker, null];
}
// handleModuleCall will handle a callModule message sent to the kernel from an
// extension or webpage.
async function handleModuleCall(
event: MessageEvent,
messagePortal: any,
callerDomain: string,
isWorker: boolean,
isInternal: false | ((message: OpenQueryResponse) => void),
) {
if (!("data" in event.data) || !("module" in event.data.data)) {
logErr(
"moduleCall",
"received moduleCall with no module field in the data",
event.data,
);
respondErr(
event,
messagePortal,
isWorker,
isInternal,
"moduleCall is missing 'module' field: " + JSON.stringify(event.data),
);
return;
}
let validCid = false;
let isResolver = false;
if (
typeof event.data.data.module === "string" &&
CID.verify(event.data.data.module)
) {
const cid = CID.decode(event.data.data.module);
validCid = true;
if (cid.type === CID_TYPES.RESOLVER) {
isResolver = true;
}
}
if (!validCid) {
logErr("moduleCall", "received moduleCall with malformed module");
respondErr(
event,
messagePortal,
isWorker,
isInternal,
"'module' field in moduleCall is expected to be a raw CID or a resolver CID",
);
return;
}
if (!("method" in event.data.data)) {
logErr(
"moduleCall",
"received moduleCall without a method set for the module",
);
respondErr(
event,
messagePortal,
isWorker,
isInternal,
"no 'data.method' specified, module does not know what method to run",
);
return;
}
if (typeof event.data.data.method !== "string") {
logErr(
"moduleCall",
"received moduleCall with malformed method",
event.data,
);
respondErr(
event,
messagePortal,
isWorker,
isInternal,
"'data.method' needs to be a string",
);
return;
}
if (event.data.data.method === "presentSeed") {
logErr(
"moduleCall",
"received malicious moduleCall - only root is allowed to use presentSeed method",
);
respondErr(
event,
messagePortal,
isWorker,
isInternal,
"presentSeed is a privileged method, only root is allowed to use it",
);
return;
}
if (!("data" in event.data.data)) {
logErr("moduleCall", "received moduleCall with no input for the module");
respondErr(
event,
messagePortal,
isWorker,
isInternal,
"no field data.data in moduleCall, data.data contains the module input",
);
return;
}
let moduleDomain = event.data.data.module; // Can change with overrides.
let finalModule = moduleDomain; // Can change with overrides.
if (isResolver) {
const registryFail = () => {
logErr("moduleCall", "received moduleCall with no known registry entry");
respondErr(
event,
messagePortal,
isWorker,
isInternal,
"registry entry for module is not found",
);
};
finalModule = getSavedRegistryEntry(moduleDomain);
if (!finalModule) {
if (!(await networkReady())) {
registryFail();
return;
}
let resolvedModule;
try {
resolvedModule = await resolveModuleRegistryEntry(moduleDomain);
} catch (e) {
registryFail();
return;
}
finalModule = resolvedModule;
}
}
// Define a helper function to create a new query to the module. It will
// both open a query on the module and also send an update message to the
// caller with the kernel nonce for this query so that the caller can
// perform query updates.
const newModuleQuery = function (mod: Module) {
let worker = mod.worker!;
// Get the nonce for this query. The nonce is a
// cryptographically secure string derived from a number and
// the user's seed. We use 'kernelNonceSalt' as a salt to
// namespace the nonces and make sure other processes don't
// accidentally end up using the same hashes.
const nonceSalt = new TextEncoder().encode("kernelNonceSalt");
const [nonceBytes] = encodeU64(BigInt(queriesNonce));
const noncePreimage = new Uint8Array(
nonceSalt.length + activeKey.length + nonceBytes.length,
);
noncePreimage.set(nonceSalt, 0);
noncePreimage.set(activeKey, nonceSalt.length);
noncePreimage.set(nonceBytes, nonceSalt.length + activeKey.length);
const nonce = bufToB64(sha512(noncePreimage));
queriesNonce = queriesNonce + 1;
queries[nonce] = {
isWorker,
isInternal: !!isInternal,
internalHandler: isInternal ?? undefined,
domain: callerDomain,
source: messagePortal,
dest: worker,
nonce: event.data.nonce,
origin: event.origin,
sw: event.data.sw,
} as OpenQuery;
// Send the message to the worker to start the query.
worker.postMessage({
nonce: nonce,
domain: callerDomain,
method: event.data.data.method,
data: event.data.data.data,
});
// If the caller is asking for the kernel nonce for this query,
// send the kernel nonce. We don't always send the kernel nonce
// because messages have material overhead.
if (event.data.sendKernelNonce === true) {
const msg = {
nonce: event.data.nonce,
method: "responseNonce",
data: {
nonce,
},
sw: event.data.sw,
};
if (isWorker) {
messagePortal.postMessage(msg);
} else {
messagePortal.postMessage(msg, event.origin);
}
}
};
// Check the worker pool to see if this module is already available.
if (moduleDomain in modules) {
const module = modules[moduleDomain];
newModuleQuery(module);
return;
}
// Check if another thread is already fetching the module.
if (moduleDomain in modulesLoading) {
const p = modulesLoading[moduleDomain];
p.then((errML: Err) => {
if (errML !== null) {
respondErr(
event,
messagePortal,
isWorker,
isInternal,
addContextToErr(errML, "module could not be loaded"),
);
return;
}
const module = modules[moduleDomain];
newModuleQuery(module);
});
return;
}
// Fetch the module in a background thread, and launch the query once the
// module is available.
modulesLoading[moduleDomain] = new Promise(async (resolve) => {
let cachedModule: Uint8Array | undefined;
try {
cachedModule = await (await moduleStore()).get(finalModule);
} catch {}
let moduleData: ReadableStream<Uint8Array> | Uint8Array | undefined;
if (cachedModule) {
const hash = CID.decode(finalModule).hash.hashBytes;
if (!equalBytes(hash, blake3(cachedModule))) {
logErr("corrupt module found in store: ", finalModule);
} else {
moduleData = cachedModule;
}
}
if (!moduleData) {
try {
moduleData = await downloadSmallObject(finalModule);
} catch (e) {
const err = addContextToErr(e, "unable to load module");
respondErr(event, messagePortal, isWorker, isInternal, err);
resolve(err);
delete modulesLoading[moduleDomain];
return;
}
}
// The call to download the skylink is async. That means it's possible that
// some other thread created the module successfully and already added it.
// Based on the rest of the code, this should not be possible, but we check
// for it anyway at runtime so that any concurrency bugs will be made
// visible through the `notableErrors` field.
//
// This check is mainly here as a verification that the rest of the kernel
// code is correct.
if (moduleDomain in modules) {
// Though this is an error, we do already have the module so we
// use the one we already loaded.
logErr("a module that was already loaded has been loaded");
notableErrors.push("module loading experienced a race condition");
const mod = modules[moduleDomain];
newModuleQuery(mod);
resolve(null);
return;
}
if (moduleData instanceof ReadableStream) {
try {
moduleData = await readableStreamToUint8Array(moduleData);
} catch (e) {
respondErr(event, messagePortal, isWorker, isInternal, e);
resolve(e);
delete modulesLoading[moduleDomain];
return;
}
}
if (!cachedModule) {
await (await moduleStore()).put(finalModule, moduleData);
}
if (!(moduleData instanceof Uint8Array)) {
moduleData = new TextEncoder().encode(moduleData);
}
// Create a new module.
const [mod, errCM] = await createModule(
moduleData,
moduleDomain,
finalModule,
);
if (errCM !== null) {
const err = addContextToErr(errCM, "unable to create module");
respondErr(event, messagePortal, isWorker, isInternal, err);
resolve(err);
delete modulesLoading[moduleDomain];
return;
}
modules[moduleDomain] = mod as Module;
newModuleQuery(mod as Module);
resolve(null);
delete modulesLoading[moduleDomain];
});
}
function handleModuleResponse(
event: MessageEvent,
mod: Module,
worker: Worker,
) {
// TODO: Need to figure out what to do with the errors here. Do we call
// 'respondErr'? That doesn't seem correct. It's not correct because if we
// end a query we need to let both sides know that the query was killed by
// the kernel.
// Technically the caller already computed these values, but it's easier to
// compute them again than to pass them as function args.
const isQueryUpdate = event.data.method === "queryUpdate";
const isResponse = event.data.method === "response";
// Check that the data field is present.
if (!("data" in event.data)) {
logErr(
"worker",
mod.domain,
"received response or update from worker with no data field",
);
return;
}
// Grab the query information so that we can properly relay the worker
// response to the original caller.
if (!(event.data.nonce in queries)) {
// If there's no corresponding query and this is a response, send an
// error.
if (isResponse) {
logErr("worker", mod.domain, "received response for an unknown nonce");
return;
}
// If there's no responding query and this isn't a response, it could
// just be an accident. queryUpdates and responseUpdates are async and
// can therefore be sent before both sides know that a query has been
// closed but not get processed untila afterwards.
//
// This can't happen with a 'response' message because the response
// message is the only message that can close the query, and there's
// only supposed to be one response message.
return;
}
// If the message is a query update, relay the update to the worker.
if (isQueryUpdate) {
const dest = queries[event.data.nonce].dest;
dest.postMessage({
nonce: event.data.nonce,
method: event.data.method,
data: event.data.data,
});
return;
}
// Check that the err field is being used correctly for response messages.
if (isResponse) {
// Check that the err field exists.
if (!("err" in event.data)) {
logErr(
"worker",
mod.domain,
"got response from worker with no err field",
);
return;
}
// Check that exactly one of 'err' and 'data' are null.
const errNull = event.data.err === null;
const dataNull = event.data.data === null;
if (errNull === dataNull) {
logErr("worker", mod.domain, "exactly one of err and data must be null");
return;
}
}
// We are sending either a response message or a responseUpdate message,
// all other possibilities have been handled.
const query = queries[event.data.nonce];
const sourceIsWorker = query.isWorker;
const sourceIsInternal = query.isInternal;
const internalHandler = query.internalHandler;
const sourceNonce = query.nonce;
const source = query.source;
const origin = query.origin;
const msg: OpenQueryResponse = {
nonce: sourceNonce,
method: event.data.method,
data: event.data.data,
sw: query.sw,
};
// For responses only, set an error and close out the query by deleting it
// from the query map.
if (isResponse) {
msg["err"] = event.data.err;
delete queries[event.data.nonce];
}
if (sourceIsWorker) {
source.postMessage(msg);
} else if (sourceIsInternal) {
internalHandler?.(msg);
} else {
source.postMessage(msg, origin);
}
}
function handleQueryUpdate(event: MessageEvent) {
// Check that the module still exists before sending a queryUpdate to
// the module.
if (!(event.data.nonce in queries)) {
logErr(
"auth",
"received queryUpdate but nonce is not recognized",
event.data,
queries,
);
return;
}
const dest = queries[event.data.nonce].dest;
dest.postMessage({
nonce: event.data.nonce,
method: event.data.method,
data: event.data.data,
sw: event.data.sw,
});
}
export async function internalModuleCall(
module: string,
method: string,
params = {},
): Promise<any> {
const callDefer = defer();
handleModuleCall(
{
data: {
data: {
module,
method,
data: params,
nonce: 0,
},
},
origin: "root",
} as any,
undefined,
"root",
false,
(message) => {
if (message.err) {
callDefer.reject(message.err);
return;
}
callDefer.resolve(message.data);
},
);
return callDefer.promise;
}
export {
Module,
handleModuleCall,
handleModuleResponse,
handleQueryUpdate,
modules,
modulesLoading,
queries,
};

38
src/registry.ts Normal file
View File

@ -0,0 +1,38 @@
const DEFAULT_MODULE_REGISTRY = new Map<string, string>(
Object.entries({
// swarm
zrjTDyEX8Mh2PdDdRj5YL2byFGrYe1ksczRwPaTRFaCGSMG:
"z2H78pADGKWPz2zWEgGKDc7jYYtSv6qBfDtKzU4Tq5zgFoejmiQD",
// peerDiscoveryRegistry
zrjD6CEchDtSex5VHjzMNSAdkJpMNfCtbxSnftgtfvtnsdY:
"z2H7AhnortTD6wL53XUdTotJZLADa7PbZCcHuSFJ6WgZ6td2bvaC",
// ircPeerDiscovery
zrjHTx8tSQFWnmZ9JzK7XmJirqJQi2WRBLYp3fASaL2AfBQ:
"z2H7D35inXTkjuxevunyq7ojv1iomXJD1svDYgkLnknk2bXc14HC",
// s5
zrjLjKVByzt233rfcjWvTQXrMfGFa11oBLydPaUk7gwnC2d:
"z2H74p9eZkzShhjfpmYLB4jpmi5qKZZHUku2eaAysWucMfcvDrpC",
// networkRegistry
zrjTCwTcK5Vco1h7cdUQKzs6yzeqm7vC5u5Lo9y1uhTyxnv:
"z2H7J3strfaEAc1kyHqMNmEPzynRipVerfCeqEhfkkcrGNNhnJUo",
}),
);
const REGISTRY_ITEM_ID = "registry";
Object.freeze(DEFAULT_MODULE_REGISTRY);
export function getSavedRegistryEntry(pubkey: string) {
const savedEntries = new Map<string, string>(
Object.entries(globalThis.localStorage.getItem(REGISTRY_ITEM_ID) ?? {}),
);
if (savedEntries.has(pubkey)) {
return savedEntries.get(pubkey) as string;
}
if (DEFAULT_MODULE_REGISTRY.has(pubkey)) {
return DEFAULT_MODULE_REGISTRY.get(pubkey) as string;
}
return null;
}

11
src/version.ts Normal file
View File

@ -0,0 +1,11 @@
// Set the distribution and version of this kernel. There may be other versions
// of the kernel in the world produced by other development teams, so openly
// declaring the version number and development team allows other pieces of
// software to determine what features are or are not supported.
//
// At some point we may want something like a capabilities array, but the
// ecosystem isn't mature enough to need that.
const KERNEL_DISTRO = "Lume Web";
const KERNEL_VERSION = "0.1.0";
export { KERNEL_DISTRO, KERNEL_VERSION };

86
src/worker.ts Normal file
View File

@ -0,0 +1,86 @@
import { CID } from "@lumeweb/libs5";
import { defer } from "@lumeweb/libkernel/module";
type WorkerMessage = (this: Worker, ev: MessageEvent) => any;
type WorkerError = (this: Worker, ev: ErrorEvent) => any;
export default class Worker {
private _code: Uint8Array;
private _errorHandler?: WorkerError;
private _messageHandler?: WorkerMessage;
private _iframe: HTMLIFrameElement;
private _iframeDefer = defer();
private _cid: CID;
constructor(code: Uint8Array, cid: CID) {
this._code = code;
this._cid = cid;
const iframe = document.createElement("iframe");
iframe.src = this.getModuleUrl();
iframe.onload = () => {
this._postMessage({
method: "workerInit",
module: this._code,
});
};
this._iframe = iframe;
document.body.appendChild(iframe);
window.addEventListener("message", (event: MessageEvent) => {
if (event.source !== iframe.contentWindow) {
return;
}
if (event.data.method === "workerMessage") {
this._messageHandler?.(
new MessageEvent("worker", { data: event.data.data }),
);
return;
}
if (event.data.method === "workerError") {
this._errorHandler?.(
new ErrorEvent("worker", {
message: event.data.data.message,
error: event.data.data.error,
}),
);
return;
}
if (event.data.method === "workerInited") {
this._iframeDefer.resolve();
return;
}
});
}
set onmessage(handler: (this: Worker, ev: MessageEvent) => any) {
this._messageHandler = handler;
}
set onerror(handler: (this: Worker, ev: ErrorEvent) => any) {
this._errorHandler = handler;
}
get ready(): Promise<any> {
return this._iframeDefer.promise;
}
postMessage(message: any) {
this._iframeDefer.promise.then(() => {
this._postMessage(message);
});
}
_postMessage(message: any) {
this._iframe.contentWindow!.postMessage(message, this.getModuleUrl());
}
private getModuleUrl() {
return `https://${this._cid.toBase32()}.module.kernel.lumeweb.com`;
}
}