@typeberry/lib 0.8.4 → 0.9.0-1c3f157

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.
Files changed (217) hide show
  1. package/package.json +6 -4
  2. package/packages/configs/index.d.ts +30 -1
  3. package/packages/configs/index.d.ts.map +1 -1
  4. package/packages/configs/index.js +4 -2
  5. package/packages/configs/typeberry-dev-full.json +29 -0
  6. package/packages/core/bytes/bytes.d.ts +1 -0
  7. package/packages/core/bytes/bytes.d.ts.map +1 -1
  8. package/packages/core/bytes/bytes.js +8 -0
  9. package/packages/core/collections/sorted-array.d.ts +1 -1
  10. package/packages/core/collections/sorted-array.d.ts.map +1 -1
  11. package/packages/core/collections/sorted-array.js +4 -2
  12. package/packages/core/collections/sorted-array.test.js +10 -0
  13. package/packages/core/collections/sorted-set.d.ts +1 -1
  14. package/packages/core/collections/sorted-set.d.ts.map +1 -1
  15. package/packages/core/collections/sorted-set.js +6 -2
  16. package/packages/core/collections/sorted-set.test.js +24 -0
  17. package/packages/core/utils/debug.d.ts +4 -2
  18. package/packages/core/utils/debug.d.ts.map +1 -1
  19. package/packages/core/utils/debug.js +18 -13
  20. package/packages/core/utils/debug.test.js +12 -6
  21. package/packages/core/utils/index.d.ts +1 -0
  22. package/packages/core/utils/index.d.ts.map +1 -1
  23. package/packages/core/utils/index.js +1 -0
  24. package/packages/core/utils/shutdown.d.ts +18 -0
  25. package/packages/core/utils/shutdown.d.ts.map +1 -0
  26. package/packages/core/utils/shutdown.js +3 -0
  27. package/packages/core/utils/shutdown.node.d.ts +5 -0
  28. package/packages/core/utils/shutdown.node.d.ts.map +1 -0
  29. package/packages/core/utils/shutdown.node.js +76 -0
  30. package/packages/core/utils/shutdown.test.d.ts +2 -0
  31. package/packages/core/utils/shutdown.test.d.ts.map +1 -0
  32. package/packages/core/utils/shutdown.test.js +164 -0
  33. package/packages/extensions/ipc/server.d.ts.map +1 -1
  34. package/packages/extensions/ipc/server.js +7 -0
  35. package/packages/jam/config-node/node-config.d.ts +22 -3
  36. package/packages/jam/config-node/node-config.d.ts.map +1 -1
  37. package/packages/jam/config-node/node-config.js +33 -6
  38. package/packages/jam/config-node/node-config.test.js +11 -4
  39. package/packages/jam/database/index.d.ts +1 -0
  40. package/packages/jam/database/index.d.ts.map +1 -1
  41. package/packages/jam/database/index.js +1 -0
  42. package/packages/jam/database/leaf-db-update.d.ts +1 -0
  43. package/packages/jam/database/leaf-db-update.d.ts.map +1 -1
  44. package/packages/jam/database/leaf-db-update.js +22 -5
  45. package/packages/jam/database/leaf-db-update.test.d.ts +2 -0
  46. package/packages/jam/database/leaf-db-update.test.d.ts.map +1 -0
  47. package/packages/jam/database/leaf-db-update.test.js +81 -0
  48. package/packages/jam/database/serialized-states-db.d.ts +1 -0
  49. package/packages/jam/database/serialized-states-db.d.ts.map +1 -1
  50. package/packages/jam/database/serialized-states-db.js +4 -0
  51. package/packages/jam/database/states.d.ts +11 -0
  52. package/packages/jam/database/states.d.ts.map +1 -1
  53. package/packages/jam/database/states.js +3 -0
  54. package/packages/jam/database/value-refs.d.ts +117 -0
  55. package/packages/jam/database/value-refs.d.ts.map +1 -0
  56. package/packages/jam/database/value-refs.js +206 -0
  57. package/packages/jam/database/value-refs.test.d.ts +2 -0
  58. package/packages/jam/database/value-refs.test.d.ts.map +1 -0
  59. package/packages/jam/database/value-refs.test.js +165 -0
  60. package/packages/jam/database-fjall/blocks.d.ts +25 -0
  61. package/packages/jam/database-fjall/blocks.d.ts.map +1 -0
  62. package/packages/jam/database-fjall/blocks.js +86 -0
  63. package/packages/jam/database-fjall/blocks.test.d.ts +2 -0
  64. package/packages/jam/database-fjall/blocks.test.d.ts.map +1 -0
  65. package/packages/jam/database-fjall/blocks.test.js +62 -0
  66. package/packages/jam/database-fjall/hybrid-states.d.ts +96 -0
  67. package/packages/jam/database-fjall/hybrid-states.d.ts.map +1 -0
  68. package/packages/jam/database-fjall/hybrid-states.js +218 -0
  69. package/packages/jam/database-fjall/hybrid-states.test.d.ts +2 -0
  70. package/packages/jam/database-fjall/hybrid-states.test.d.ts.map +1 -0
  71. package/packages/jam/database-fjall/hybrid-states.test.js +113 -0
  72. package/packages/jam/database-fjall/index.d.ts +5 -0
  73. package/packages/jam/database-fjall/index.d.ts.map +1 -0
  74. package/packages/jam/database-fjall/index.js +4 -0
  75. package/packages/jam/database-fjall/root.d.ts +64 -0
  76. package/packages/jam/database-fjall/root.d.ts.map +1 -0
  77. package/packages/jam/database-fjall/root.js +105 -0
  78. package/packages/jam/database-fjall/states.d.ts +31 -0
  79. package/packages/jam/database-fjall/states.d.ts.map +1 -0
  80. package/packages/jam/database-fjall/states.js +99 -0
  81. package/packages/jam/database-fjall/states.test.d.ts +2 -0
  82. package/packages/jam/database-fjall/states.test.d.ts.map +1 -0
  83. package/packages/jam/database-fjall/states.test.js +150 -0
  84. package/packages/jam/database-lmdb/hybrid-states.d.ts +12 -0
  85. package/packages/jam/database-lmdb/hybrid-states.d.ts.map +1 -1
  86. package/packages/jam/database-lmdb/hybrid-states.js +45 -4
  87. package/packages/jam/database-lmdb/states.d.ts +1 -0
  88. package/packages/jam/database-lmdb/states.d.ts.map +1 -1
  89. package/packages/jam/database-lmdb/states.js +5 -0
  90. package/packages/jam/jamnp-s/tasks/ticket-distribution.d.ts +18 -10
  91. package/packages/jam/jamnp-s/tasks/ticket-distribution.d.ts.map +1 -1
  92. package/packages/jam/jamnp-s/tasks/ticket-distribution.js +44 -68
  93. package/packages/jam/jamnp-s/tasks/ticket-distribution.test.js +30 -8
  94. package/packages/jam/node/export.d.ts.map +1 -1
  95. package/packages/jam/node/export.js +18 -9
  96. package/packages/jam/node/main-fuzz.d.ts +4 -1
  97. package/packages/jam/node/main-fuzz.d.ts.map +1 -1
  98. package/packages/jam/node/main-fuzz.js +142 -55
  99. package/packages/jam/node/main-importer.d.ts +15 -3
  100. package/packages/jam/node/main-importer.d.ts.map +1 -1
  101. package/packages/jam/node/main-importer.js +30 -14
  102. package/packages/jam/node/main.d.ts.map +1 -1
  103. package/packages/jam/node/main.js +42 -15
  104. package/packages/jam/node/workers.d.ts +4 -4
  105. package/packages/jam/node/workers.d.ts.map +1 -1
  106. package/packages/jam/safrole/bandersnatch-vrf.d.ts +24 -4
  107. package/packages/jam/safrole/bandersnatch-vrf.d.ts.map +1 -1
  108. package/packages/jam/safrole/bandersnatch-vrf.js +63 -26
  109. package/packages/jam/safrole/bandersnatch-vrf.test.js +12 -9
  110. package/packages/jam/safrole/bandersnatch-wasm.d.ts +10 -0
  111. package/packages/jam/safrole/bandersnatch-wasm.d.ts.map +1 -1
  112. package/packages/jam/safrole/bandersnatch-wasm.js +12 -0
  113. package/packages/jam/safrole/safrole.js +5 -5
  114. package/packages/jam/safrole/safrole.test.js +13 -13
  115. package/packages/jam/ticket-pool/index.d.ts +4 -0
  116. package/packages/jam/ticket-pool/index.d.ts.map +1 -0
  117. package/packages/jam/ticket-pool/index.js +3 -0
  118. package/packages/jam/ticket-pool/pending-ticket-pool.d.ts +30 -0
  119. package/packages/jam/ticket-pool/pending-ticket-pool.d.ts.map +1 -0
  120. package/packages/jam/ticket-pool/pending-ticket-pool.js +56 -0
  121. package/packages/jam/ticket-pool/pending-ticket-pool.test.d.ts +2 -0
  122. package/packages/jam/ticket-pool/pending-ticket-pool.test.d.ts.map +1 -0
  123. package/packages/jam/ticket-pool/pending-ticket-pool.test.js +67 -0
  124. package/packages/jam/ticket-pool/ticket-validator.d.ts +47 -0
  125. package/packages/jam/ticket-pool/ticket-validator.d.ts.map +1 -0
  126. package/packages/jam/ticket-pool/ticket-validator.js +34 -0
  127. package/packages/jam/ticket-pool/ticket-validator.test.d.ts +2 -0
  128. package/packages/jam/ticket-pool/ticket-validator.test.d.ts.map +1 -0
  129. package/packages/jam/ticket-pool/ticket-validator.test.js +35 -0
  130. package/packages/jam/ticket-pool/verified-ticket-pool.d.ts +26 -0
  131. package/packages/jam/ticket-pool/verified-ticket-pool.d.ts.map +1 -0
  132. package/packages/jam/ticket-pool/verified-ticket-pool.js +41 -0
  133. package/packages/jam/ticket-pool/verified-ticket-pool.test.d.ts +2 -0
  134. package/packages/jam/ticket-pool/verified-ticket-pool.test.d.ts.map +1 -0
  135. package/packages/jam/ticket-pool/verified-ticket-pool.test.js +54 -0
  136. package/packages/workers/api/config.d.ts +2 -2
  137. package/packages/workers/api/config.d.ts.map +1 -1
  138. package/packages/workers/api/config.js +1 -1
  139. package/packages/workers/api/port.d.ts +5 -1
  140. package/packages/workers/api/port.d.ts.map +1 -1
  141. package/packages/workers/api/port.js +56 -13
  142. package/packages/workers/api/port.test.js +35 -0
  143. package/packages/workers/api-node/config.d.ts +65 -9
  144. package/packages/workers/api-node/config.d.ts.map +1 -1
  145. package/packages/workers/api-node/config.js +151 -26
  146. package/packages/workers/api-node/config.test.js +88 -2
  147. package/packages/workers/api-node/port.d.ts +3 -0
  148. package/packages/workers/api-node/port.d.ts.map +1 -1
  149. package/packages/workers/api-node/port.js +31 -2
  150. package/packages/workers/api-node/port.test.js +17 -0
  151. package/packages/workers/api-node/protocol.d.ts +3 -3
  152. package/packages/workers/api-node/protocol.d.ts.map +1 -1
  153. package/packages/workers/api-node/protocol.js +18 -12
  154. package/packages/workers/block-authorship/{generator.d.ts → block-generator.d.ts} +5 -5
  155. package/packages/workers/block-authorship/block-generator.d.ts.map +1 -0
  156. package/packages/workers/block-authorship/{generator.js → block-generator.js} +3 -3
  157. package/packages/workers/block-authorship/block-generator.test.d.ts +2 -0
  158. package/packages/workers/block-authorship/block-generator.test.d.ts.map +1 -0
  159. package/packages/workers/block-authorship/{generator.test.js → block-generator.test.js} +8 -8
  160. package/packages/workers/block-authorship/epoch-authoring-slots.d.ts +35 -0
  161. package/packages/workers/block-authorship/epoch-authoring-slots.d.ts.map +1 -0
  162. package/packages/workers/block-authorship/epoch-authoring-slots.js +86 -0
  163. package/packages/workers/block-authorship/epoch-tracker.d.ts +29 -0
  164. package/packages/workers/block-authorship/epoch-tracker.d.ts.map +1 -0
  165. package/packages/workers/block-authorship/epoch-tracker.js +80 -0
  166. package/packages/workers/block-authorship/index.d.ts.map +1 -1
  167. package/packages/workers/block-authorship/index.js +1 -1
  168. package/packages/workers/block-authorship/main.d.ts +3 -0
  169. package/packages/workers/block-authorship/main.d.ts.map +1 -1
  170. package/packages/workers/block-authorship/main.js +198 -316
  171. package/packages/workers/block-authorship/ticket-generator/bootstrap-main.d.ts +2 -0
  172. package/packages/workers/block-authorship/ticket-generator/bootstrap-main.d.ts.map +1 -0
  173. package/packages/workers/block-authorship/ticket-generator/bootstrap-main.js +23 -0
  174. package/packages/workers/block-authorship/ticket-generator/index.d.ts +16 -0
  175. package/packages/workers/block-authorship/ticket-generator/index.d.ts.map +1 -0
  176. package/packages/workers/block-authorship/ticket-generator/index.js +62 -0
  177. package/packages/workers/block-authorship/ticket-generator/protocol.d.ts +50 -0
  178. package/packages/workers/block-authorship/ticket-generator/protocol.d.ts.map +1 -0
  179. package/packages/workers/block-authorship/ticket-generator/protocol.js +54 -0
  180. package/packages/workers/block-authorship/{ticket-generator.d.ts → ticket-generator/ticket-generator.d.ts} +4 -0
  181. package/packages/workers/block-authorship/ticket-generator/ticket-generator.d.ts.map +1 -0
  182. package/packages/workers/block-authorship/{ticket-generator.js → ticket-generator/ticket-generator.js} +19 -9
  183. package/packages/workers/block-authorship/ticket-generator/ticket-generator.test.d.ts.map +1 -0
  184. package/packages/workers/block-authorship/{ticket-generator.test.js → ticket-generator/ticket-generator.test.js} +13 -9
  185. package/packages/workers/block-authorship/ticket-generator/worker-pool.d.ts +36 -0
  186. package/packages/workers/block-authorship/ticket-generator/worker-pool.d.ts.map +1 -0
  187. package/packages/workers/block-authorship/ticket-generator/worker-pool.js +111 -0
  188. package/packages/workers/block-authorship/ticket-validator.d.ts +31 -0
  189. package/packages/workers/block-authorship/ticket-validator.d.ts.map +1 -0
  190. package/packages/workers/block-authorship/ticket-validator.js +59 -0
  191. package/packages/workers/comms-authorship-network/protocol.d.ts +14 -4
  192. package/packages/workers/comms-authorship-network/protocol.d.ts.map +1 -1
  193. package/packages/workers/comms-authorship-network/protocol.js +12 -6
  194. package/packages/workers/comms-authorship-network/tickets-message.d.ts +0 -14
  195. package/packages/workers/comms-authorship-network/tickets-message.d.ts.map +1 -1
  196. package/packages/workers/comms-authorship-network/tickets-message.js +0 -17
  197. package/packages/workers/importer/finality.d.ts +2 -0
  198. package/packages/workers/importer/finality.d.ts.map +1 -1
  199. package/packages/workers/importer/finality.js +8 -1
  200. package/packages/workers/importer/importer.d.ts +2 -2
  201. package/packages/workers/importer/importer.d.ts.map +1 -1
  202. package/packages/workers/importer/importer.js +6 -5
  203. package/packages/workers/importer/main.d.ts +1 -1
  204. package/packages/workers/importer/main.d.ts.map +1 -1
  205. package/packages/workers/importer/main.js +1 -1
  206. package/packages/workers/importer/stats.d.ts +1 -3
  207. package/packages/workers/importer/stats.d.ts.map +1 -1
  208. package/packages/workers/importer/stats.js +12 -12
  209. package/packages/workers/jam-network/main.d.ts.map +1 -1
  210. package/packages/workers/jam-network/main.js +26 -5
  211. package/packages/workers/block-authorship/generator.d.ts.map +0 -1
  212. package/packages/workers/block-authorship/generator.test.d.ts +0 -2
  213. package/packages/workers/block-authorship/generator.test.d.ts.map +0 -1
  214. package/packages/workers/block-authorship/ticket-generator.d.ts.map +0 -1
  215. package/packages/workers/block-authorship/ticket-generator.test.d.ts.map +0 -1
  216. /package/packages/configs/{typeberry-dev.json → typeberry-dev-tiny.json} +0 -0
  217. /package/packages/workers/block-authorship/{ticket-generator.test.d.ts → ticket-generator/ticket-generator.test.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"node-config.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/config-node/node-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,EAAE,KAAK,QAAQ,EAAuB,MAAM,wBAAwB,CAAC;AAG5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAInD,+DAA+D;AAC/D,eAAO,MAAM,UAAU,QAAQ,CAAC;AAChC,2BAA2B;AAC3B,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC,eAAO,MAAM,aAAa;;;;CAIzB,CAAC;AAEF,0BAA0B;AAC1B,oBAAY,cAAc;IACxB,uBAAuB;IACvB,IAAI,SAAS;IACb,uBAAuB;IACvB,IAAI,SAAS;CACd;AAED,eAAO,MAAM,sBAAsB,EAS7B,QAAQ,CAAC,cAAc,CAAC,CAAC;AAE/B,qBAAa,iBAAiB;aAqBV,OAAO,EAAE,MAAM;aACf,OAAO,EAAE,MAAM;aACf,MAAM,EAAE,cAAc;aACtB,SAAS,EAAE,YAAY;IACvC,iEAAiE;aACjD,gBAAgB,EAAE,MAAM,GAAG,SAAS;aACpC,UAAU,EAAE,iBAAiB;IA1B/C,MAAM,CAAC,QAAQ,kFAUb;IAEF,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,UAAU,EAAE,EAAE,UAAU,CAAC,iBAAiB,CAAC;IAOlH,OAAO;CASR;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,iBAAiB,CAkDlG"}
1
+ {"version":3,"file":"node-config.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/config-node/node-config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,EAAE,KAAK,QAAQ,EAAuB,MAAM,wBAAwB,CAAC;AAG5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAInD,+DAA+D;AAC/D,eAAO,MAAM,eAAe,QAAQ,CAAC;AACrC,eAAO,MAAM,eAAe,aAAa,CAAC;AAE1C,2BAA2B;AAC3B,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC,eAAO,MAAM,aAAa;;;;CAIzB,CAAC;AAEF,0BAA0B;AAC1B,oBAAY,cAAc;IACxB,uBAAuB;IACvB,IAAI,SAAS;IACb,uBAAuB;IACvB,IAAI,SAAS;CACd;AAED,gDAAgD;AAChD,oBAAY,mBAAmB;IAC7B,oGAAoG;IACpG,IAAI,SAAS;IACb,KAAK,UAAU;CAChB;AAED,eAAO,MAAM,sBAAsB,EAS7B,QAAQ,CAAC,cAAc,CAAC,CAAC;AAE/B,eAAO,MAAM,2BAA2B,EASlC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;AAEpC,KAAK,qBAAqB,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,cAAc,CAAC;IACvB,UAAU,EAAE,YAAY,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,UAAU,EAAE,iBAAiB,CAAC;CAC/B,CAAC;AAEF,qBAAa,iBAAiB;aAsCV,OAAO,EAAE,MAAM;aACf,OAAO,EAAE,MAAM;aACf,MAAM,EAAE,cAAc;aACtB,SAAS,EAAE,YAAY;IACvC,iEAAiE;aACjD,gBAAgB,EAAE,MAAM,GAAG,SAAS;IACpD,uEAAuE;aACvD,YAAY,EAAE,mBAAmB;aACjC,UAAU,EAAE,iBAAiB;IA7C/C,MAAM,CAAC,QAAQ,kFAWb;IAEF,MAAM,CAAC,GAAG,CAAC,EACT,OAAO,EACP,OAAO,EACP,MAAM,EACN,UAAU,EACV,kBAAkB,EAClB,aAAa,EACb,UAAU,GACX,EAAE,qBAAqB;IAexB,OAAO;CAWR;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,iBAAiB,CAuDlG"}
@@ -9,7 +9,8 @@ import { AuthorshipOptions } from "./authorship.js";
9
9
  import { JipChainSpec } from "./jip-chain-spec.js";
10
10
  const logger = Logger.new(import.meta.filename, "config");
11
11
  /** Development config. Will accept unsealed blocks for now. */
12
- export const DEV_CONFIG = "dev";
12
+ export const DEV_TINY_CONFIG = "dev";
13
+ export const DEV_FULL_CONFIG = "dev-full";
13
14
  /** Default config file. */
14
15
  export const DEFAULT_CONFIG = "default";
15
16
  export const NODE_DEFAULTS = {
@@ -25,6 +26,13 @@ export var KnownChainSpec;
25
26
  /** Full chain spec. */
26
27
  KnownChainSpec["Full"] = "full";
27
28
  })(KnownChainSpec || (KnownChainSpec = {}));
29
+ /** Persistent regular-node database backend. */
30
+ export var RegularStateBackend;
31
+ (function (RegularStateBackend) {
32
+ /** @deprecated lmdb remains available as an explicit fallback, but fjall is the default backend. */
33
+ RegularStateBackend["Lmdb"] = "lmdb";
34
+ RegularStateBackend["Fjall"] = "fjall";
35
+ })(RegularStateBackend || (RegularStateBackend = {}));
28
36
  export const knownChainSpecFromJson = json.fromString((input, ctx) => {
29
37
  switch (input) {
30
38
  case KnownChainSpec.Tiny:
@@ -35,12 +43,23 @@ export const knownChainSpecFromJson = json.fromString((input, ctx) => {
35
43
  throw Error(`unknown network flavor: ${input} at ${ctx}`);
36
44
  }
37
45
  });
46
+ export const regularStateBackendFromJson = json.fromString((input, ctx) => {
47
+ switch (input) {
48
+ case RegularStateBackend.Lmdb:
49
+ return RegularStateBackend.Lmdb;
50
+ case RegularStateBackend.Fjall:
51
+ return RegularStateBackend.Fjall;
52
+ default:
53
+ throw Error(`unknown state backend: ${input} at ${ctx}`);
54
+ }
55
+ });
38
56
  export class NodeConfiguration {
39
57
  $schema;
40
58
  version;
41
59
  flavor;
42
60
  chainSpec;
43
61
  databaseBasePath;
62
+ stateBackend;
44
63
  authorship;
45
64
  static fromJson = json.object({
46
65
  $schema: "string",
@@ -48,22 +67,26 @@ export class NodeConfiguration {
48
67
  flavor: knownChainSpecFromJson,
49
68
  chain_spec: JipChainSpec.fromJson,
50
69
  database_base_path: json.optional("string"),
70
+ state_backend: json.optional(regularStateBackendFromJson),
51
71
  authorship: AuthorshipOptions.fromJson,
52
72
  }, NodeConfiguration.new);
53
- static new({ $schema, version, flavor, chain_spec, database_base_path, authorship }) {
73
+ static new({ $schema, version, flavor, chain_spec, database_base_path, state_backend, authorship, }) {
54
74
  if (version !== 1) {
55
75
  throw new Error("Only version=1 config is supported.");
56
76
  }
57
- return new NodeConfiguration($schema, version, flavor, chain_spec, database_base_path ?? undefined, authorship);
77
+ return new NodeConfiguration($schema, version, flavor, chain_spec, database_base_path ?? undefined, state_backend ?? RegularStateBackend.Fjall, authorship);
58
78
  }
59
79
  constructor($schema, version, flavor, chainSpec,
60
80
  /** If database path is not provided, we load an in-memory db. */
61
- databaseBasePath, authorship) {
81
+ databaseBasePath,
82
+ /** Persistent database backend used when `databaseBasePath` is set. */
83
+ stateBackend, authorship) {
62
84
  this.$schema = $schema;
63
85
  this.version = version;
64
86
  this.flavor = flavor;
65
87
  this.chainSpec = chainSpec;
66
88
  this.databaseBasePath = databaseBasePath;
89
+ this.stateBackend = stateBackend;
67
90
  this.authorship = authorship;
68
91
  }
69
92
  }
@@ -72,8 +95,12 @@ export function loadConfig(config, withRelPath) {
72
95
  let mergedJson = {};
73
96
  for (const entry of config) {
74
97
  logger.log `🔧 Applying '${entry}'`;
75
- if (entry === DEV_CONFIG) {
76
- mergedJson = structuredClone(configs.dev); // clone to avoid mutating the original config. not doing a merge since dev and default should theoretically replace all properties.
98
+ if (entry === DEV_TINY_CONFIG) {
99
+ mergedJson = structuredClone(configs.devTiny); // clone to avoid mutating the original config. not doing a merge since dev and default should theoretically replace all properties.
100
+ continue;
101
+ }
102
+ if (entry === DEV_FULL_CONFIG) {
103
+ mergedJson = structuredClone(configs.devFull); // clone to avoid mutating the original config. not doing a merge since dev and default should theoretically replace all properties.
77
104
  continue;
78
105
  }
79
106
  if (entry === DEFAULT_CONFIG) {
@@ -5,7 +5,7 @@ import { configs } from "#@typeberry/configs";
5
5
  import polkajamConfig from "#@typeberry/configs/typeberry-polkajam-dev.json" with { type: "json" };
6
6
  import { parseFromJson } from "#@typeberry/json-parser";
7
7
  import { workspacePathFix } from "#@typeberry/utils";
8
- import { KnownChainSpec, loadConfig, NodeConfiguration } from "./node-config.js";
8
+ import { KnownChainSpec, loadConfig, NodeConfiguration, RegularStateBackend } from "./node-config.js";
9
9
  const withRelPath = workspacePathFix(`${import.meta.dirname}/../..`);
10
10
  const NODE_CONFIG_TEST = {
11
11
  $schema: "https://typeberry.dev/schemas/config-v1.schema.json",
@@ -40,6 +40,13 @@ describe("Importing Node Configuration", () => {
40
40
  it("should read the database base path", () => {
41
41
  assert.deepStrictEqual(config.databaseBasePath, "/tmp/jam-node-db");
42
42
  });
43
+ it("defaults to the fjall state backend", () => {
44
+ assert.deepStrictEqual(config.stateBackend, RegularStateBackend.Fjall);
45
+ });
46
+ it("should read the state backend", () => {
47
+ const lmdbConfig = parseFromJson({ ...NODE_CONFIG_TEST, state_backend: "lmdb" }, NodeConfiguration.fromJson);
48
+ assert.deepStrictEqual(lmdbConfig.stateBackend, RegularStateBackend.Lmdb);
49
+ });
43
50
  it("should read the chain spec", () => {
44
51
  assert.deepStrictEqual(config.chainSpec.id, "testnet");
45
52
  assert(config.chainSpec.bootnodes !== undefined);
@@ -70,7 +77,7 @@ describe("loadConfig", () => {
70
77
  });
71
78
  it("should load dev config", () => {
72
79
  const config = loadConfig(["dev"], withRelPath);
73
- assert.deepStrictEqual(config, parseFromJson(configs.dev, NodeConfiguration.fromJson));
80
+ assert.deepStrictEqual(config, parseFromJson(configs.devTiny, NodeConfiguration.fromJson));
74
81
  });
75
82
  it("should parse inline json config and deep merge onto previous entries", () => {
76
83
  const config = loadConfig(["default", JSON.stringify({ database_base_path: "/test/path", chain_spec: { bootnodes: [] } })], withRelPath);
@@ -138,9 +145,9 @@ describe("loadConfig", () => {
138
145
  `.database_base_path="/test/path-1"`,
139
146
  ], withRelPath);
140
147
  assert.deepStrictEqual(config, parseFromJson({
141
- ...configs.dev,
148
+ ...configs.devTiny,
142
149
  database_base_path: "/test/path-1",
143
- chain_spec: { ...configs.dev.chain_spec, bootnodes: [] },
150
+ chain_spec: { ...configs.devTiny.chain_spec, bootnodes: [] },
144
151
  }, NodeConfiguration.fromJson));
145
152
  });
146
153
  it("should throw an error if an invalid json file is provided", () => {
@@ -4,4 +4,5 @@ export * from "./leaf-db-update.js";
4
4
  export * from "./root.js";
5
5
  export * from "./serialized-states-db.js";
6
6
  export * from "./states.js";
7
+ export * from "./value-refs.js";
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,WAAW,CAAC;AAC1B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,WAAW,CAAC;AAC1B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC"}
@@ -4,3 +4,4 @@ export * from "./leaf-db-update.js";
4
4
  export * from "./root.js";
5
5
  export * from "./serialized-states-db.js";
6
6
  export * from "./states.js";
7
+ export * from "./value-refs.js";
@@ -5,6 +5,7 @@ import { StateEntryUpdateAction, type StateKey } from "#@typeberry/state-merklei
5
5
  import { type LeafNode, type ValueHash } from "#@typeberry/trie";
6
6
  export declare function updateLeafs(leafs: SortedSet<LeafNode>, blake2b: Blake2b, data: Iterable<[StateEntryUpdateAction, StateKey | TruncatedHash, BytesBlob]>): {
7
7
  values: [ValueHash, BytesBlob][];
8
+ removed: ValueHash[];
8
9
  leafs: SortedSet<LeafNode>;
9
10
  };
10
11
  //# sourceMappingURL=leaf-db-update.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"leaf-db-update.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database/leaf-db-update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,KAAK,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AACvF,OAAO,EAAgB,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI9E,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,EAC1B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,QAAQ,CAAC,CAAC,sBAAsB,EAAE,QAAQ,GAAG,aAAa,EAAE,SAAS,CAAC,CAAC,GAC5E;IACD,MAAM,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC;IACjC,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;CAC5B,CAwBA"}
1
+ {"version":3,"file":"leaf-db-update.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database/leaf-db-update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,KAAK,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AACvF,OAAO,EAAgB,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI9E,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,EAC1B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,QAAQ,CAAC,CAAC,sBAAsB,EAAE,QAAQ,GAAG,aAAa,EAAE,SAAS,CAAC,CAAC,GAC5E;IACD,MAAM,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC;IACjC,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;CAC5B,CAyCA"}
@@ -7,18 +7,34 @@ export function updateLeafs(leafs, blake2b, data) {
7
7
  const blake2bTrieHasher = getBlake2bTrieHasher(blake2b);
8
8
  // We will collect all values that don't fit directly into leaf nodes.
9
9
  const values = [];
10
+ // Value hashes that are no longer referenced by the leaf they were stored under.
11
+ // NOTE this does not yet mean they can be removed from the DB - the same value
12
+ // may still be referenced by another leaf or another state. It's up to value
13
+ // ref-counting to decide that.
14
+ const removed = [];
10
15
  for (const [action, key, value] of data) {
11
16
  if (action === StateEntryUpdateAction.Insert) {
12
17
  const leafNode = InMemoryTrie.constructLeaf(blake2bTrieHasher, key.asOpaque(), value);
13
- leafs.replace(leafNode);
14
- if (!leafNode.hasEmbeddedValue()) {
15
- values.push([leafNode.getValueHash(), value]);
18
+ const displaced = leafs.replace(leafNode);
19
+ const newHash = leafNode.hasEmbeddedValue() ? null : leafNode.getValueHash();
20
+ const oldHash = displaced !== undefined && !displaced.hasEmbeddedValue() ? displaced.getValueHash() : null;
21
+ // Re-inserting the exact same value under the same key is a no-op for the DB.
22
+ if (newHash !== null && oldHash !== null && newHash.isEqualTo(oldHash)) {
23
+ continue;
24
+ }
25
+ if (newHash !== null) {
26
+ values.push([newHash, value]);
27
+ }
28
+ if (oldHash !== null) {
29
+ removed.push(oldHash);
16
30
  }
17
31
  }
18
32
  else if (action === StateEntryUpdateAction.Remove) {
19
33
  const leafNode = InMemoryTrie.constructLeaf(blake2bTrieHasher, key.asOpaque(), BytesBlob.empty());
20
- leafs.removeOne(leafNode);
21
- // TODO [ToDr] Handle ref-counting values or updating some header-hash-based references.
34
+ const removedLeaf = leafs.removeOne(leafNode);
35
+ if (removedLeaf !== undefined && !removedLeaf.hasEmbeddedValue()) {
36
+ removed.push(removedLeaf.getValueHash());
37
+ }
22
38
  }
23
39
  else {
24
40
  assertNever(action);
@@ -26,6 +42,7 @@ export function updateLeafs(leafs, blake2b, data) {
26
42
  }
27
43
  return {
28
44
  values,
45
+ removed,
29
46
  leafs,
30
47
  };
31
48
  }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=leaf-db-update.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"leaf-db-update.test.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database/leaf-db-update.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,81 @@
1
+ import assert from "node:assert";
2
+ import { before, describe, it } from "node:test";
3
+ import { Bytes, BytesBlob } from "#@typeberry/bytes";
4
+ import { SortedSet } from "#@typeberry/collections";
5
+ import { Blake2b, HASH_SIZE } from "#@typeberry/hash";
6
+ import { StateEntryUpdateAction } from "#@typeberry/state-merkleization";
7
+ import { leafComparator } from "#@typeberry/trie";
8
+ import { updateLeafs } from "./leaf-db-update.js";
9
+ let blake2b;
10
+ before(async () => {
11
+ blake2b = await Blake2b.createHasher();
12
+ });
13
+ function key(n) {
14
+ return Bytes.fill(HASH_SIZE, n).asOpaque();
15
+ }
16
+ /** A value larger than 32 bytes, so it does not fit into the leaf and is hash-referenced. */
17
+ function bigValue(b) {
18
+ return Bytes.fill(64, b);
19
+ }
20
+ /** A value that fits directly into the leaf node. */
21
+ function smallValue(b) {
22
+ return Bytes.fill(4, b);
23
+ }
24
+ function emptyLeafs() {
25
+ return SortedSet.fromArray(leafComparator, []);
26
+ }
27
+ function asStrings(hashes) {
28
+ return hashes.map((h) => h.toString());
29
+ }
30
+ describe("updateLeafs", () => {
31
+ it("collects a freshly inserted non-embedded value and removes nothing", () => {
32
+ const leafs = emptyLeafs();
33
+ const res = updateLeafs(leafs, blake2b, [[StateEntryUpdateAction.Insert, key(1), bigValue(0xaa)]]);
34
+ assert.strictEqual(res.values.length, 1);
35
+ assert.deepStrictEqual(res.removed, []);
36
+ });
37
+ it("collects nothing for an embedded value", () => {
38
+ const leafs = emptyLeafs();
39
+ const res = updateLeafs(leafs, blake2b, [[StateEntryUpdateAction.Insert, key(1), smallValue(0xaa)]]);
40
+ assert.deepStrictEqual(res.values, []);
41
+ assert.deepStrictEqual(res.removed, []);
42
+ });
43
+ it("emits the displaced value hash in `removed` when a leaf is replaced", () => {
44
+ const leafs = emptyLeafs();
45
+ const first = updateLeafs(leafs, blake2b, [[StateEntryUpdateAction.Insert, key(1), bigValue(0xaa)]]);
46
+ const oldHash = first.values[0][0];
47
+ const res = updateLeafs(leafs, blake2b, [[StateEntryUpdateAction.Insert, key(1), bigValue(0xbb)]]);
48
+ assert.strictEqual(res.values.length, 1);
49
+ assert.deepStrictEqual(asStrings(res.removed), asStrings([oldHash]));
50
+ });
51
+ it("cancels out when the same value is re-inserted at the same key", () => {
52
+ const leafs = emptyLeafs();
53
+ updateLeafs(leafs, blake2b, [[StateEntryUpdateAction.Insert, key(1), bigValue(0xaa)]]);
54
+ const res = updateLeafs(leafs, blake2b, [[StateEntryUpdateAction.Insert, key(1), bigValue(0xaa)]]);
55
+ assert.deepStrictEqual(res.values, []);
56
+ assert.deepStrictEqual(res.removed, []);
57
+ });
58
+ it("emits the old hash when a non-embedded value becomes embedded", () => {
59
+ const leafs = emptyLeafs();
60
+ const first = updateLeafs(leafs, blake2b, [[StateEntryUpdateAction.Insert, key(1), bigValue(0xaa)]]);
61
+ const oldHash = first.values[0][0];
62
+ const res = updateLeafs(leafs, blake2b, [[StateEntryUpdateAction.Insert, key(1), smallValue(0xbb)]]);
63
+ assert.deepStrictEqual(res.values, []);
64
+ assert.deepStrictEqual(asStrings(res.removed), asStrings([oldHash]));
65
+ });
66
+ it("emits the removed value hash when a non-embedded leaf is removed", () => {
67
+ const leafs = emptyLeafs();
68
+ const first = updateLeafs(leafs, blake2b, [[StateEntryUpdateAction.Insert, key(1), bigValue(0xaa)]]);
69
+ const oldHash = first.values[0][0];
70
+ const res = updateLeafs(leafs, blake2b, [[StateEntryUpdateAction.Remove, key(1), BytesBlob.empty()]]);
71
+ assert.deepStrictEqual(res.values, []);
72
+ assert.deepStrictEqual(asStrings(res.removed), asStrings([oldHash]));
73
+ });
74
+ it("removes nothing when an embedded leaf is removed", () => {
75
+ const leafs = emptyLeafs();
76
+ updateLeafs(leafs, blake2b, [[StateEntryUpdateAction.Insert, key(1), smallValue(0xaa)]]);
77
+ const res = updateLeafs(leafs, blake2b, [[StateEntryUpdateAction.Remove, key(1), BytesBlob.empty()]]);
78
+ assert.deepStrictEqual(res.values, []);
79
+ assert.deepStrictEqual(res.removed, []);
80
+ });
81
+ });
@@ -27,6 +27,7 @@ export declare class InMemorySerializedStates implements StatesDb<SerializedStat
27
27
  getStateRoot(state: SerializedState<LeafDb>): Promise<StateRootHash>;
28
28
  updateAndSetState(header: HeaderHash, state: SerializedState<LeafDb>, update: Partial<State & ServicesUpdate>): Promise<Result<OK, StateUpdateError>>;
29
29
  getState(header: HeaderHash): SerializedState<LeafDb> | null;
30
+ commitFinalized(_headers: HeaderHash[]): void;
30
31
  markUnused(header: HeaderHash): void;
31
32
  close(): Promise<void>;
32
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"serialized-states-db.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database/serialized-states-db.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGlE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EACL,eAAe,EACf,KAAK,YAAY,EAGlB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE5E,qCAAqC;AACrC,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;AAEhG,sCAAsC;AACtC,qBAAa,wBAAyB,YAAW,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,EAAE,YAAY,CAAC,YAAY,CAAC;IAc1G,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAd1B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAyE;IAC5F,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8D;WAE1E,GAAG,CAAC,EAAE,SAAS,EAAE,EAAE;QAAE,SAAS,EAAE,SAAS,CAAA;KAAE;IAKxD,MAAM,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE;QAAE,SAAS,EAAE,SAAS,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE;IAIpF,OAAO;IAKD,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAiBxG,YAAY,CAAC,KAAK,EAAE,eAAe,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;IAIpE,iBAAiB,CACrB,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,eAAe,CAAC,MAAM,CAAC,EAC9B,MAAM,EAAE,OAAO,CAAC,KAAK,GAAG,cAAc,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAsBxC,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,GAAG,IAAI;IAkB5D,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAI9B,KAAK;CACZ"}
1
+ {"version":3,"file":"serialized-states-db.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database/serialized-states-db.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGlE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EACL,eAAe,EACf,KAAK,YAAY,EAGlB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE5E,qCAAqC;AACrC,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;AAEhG,sCAAsC;AACtC,qBAAa,wBAAyB,YAAW,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,EAAE,YAAY,CAAC,YAAY,CAAC;IAc1G,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAd1B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAyE;IAC5F,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8D;WAE1E,GAAG,CAAC,EAAE,SAAS,EAAE,EAAE;QAAE,SAAS,EAAE,SAAS,CAAA;KAAE;IAKxD,MAAM,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE;QAAE,SAAS,EAAE,SAAS,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE;IAIpF,OAAO;IAKD,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAiBxG,YAAY,CAAC,KAAK,EAAE,eAAe,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;IAIpE,iBAAiB,CACrB,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,eAAe,CAAC,MAAM,CAAC,EAC9B,MAAM,EAAE,OAAO,CAAC,KAAK,GAAG,cAAc,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAsBxC,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,GAAG,IAAI;IAkB5D,eAAe,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI;IAK7C,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAI9B,KAAK;CACZ"}
@@ -70,6 +70,10 @@ export class InMemorySerializedStates {
70
70
  });
71
71
  return SerializedState.new(this.spec, this.blake2b, leafDb);
72
72
  }
73
+ commitFinalized(_headers) {
74
+ // No value pruning here: this in-memory db keeps every value in a plain map
75
+ // and is not the long-running fuzz target the refcounting is meant for.
76
+ }
73
77
  markUnused(header) {
74
78
  this.db.delete(header);
75
79
  }
@@ -33,6 +33,16 @@ export interface StatesDb<T extends State = State> {
33
33
  updateAndSetState(header: HeaderHash, state: T, update: Partial<State & ServicesUpdate>): Promise<Result<OK, StateUpdateError>>;
34
34
  /** Retrieve posterior state of given header. */
35
35
  getState(header: HeaderHash): T | null;
36
+ /**
37
+ * Notify the backend about newly finalized blocks, in ancestor-first order.
38
+ *
39
+ * Backends that share data between states (e.g. a content-addressed values DB)
40
+ * use this to move the blocks' references from speculative to finalized.
41
+ * MUST be called before `markUnused` of the same finality round, otherwise
42
+ * the newly finalized blocks would be treated as dead forks and values still
43
+ * referenced by the finalized state could be dropped.
44
+ */
45
+ commitFinalized(headers: HeaderHash[]): void;
36
46
  /** Mark state as no longer needed. Backend may remove it asynchronously. */
37
47
  markUnused(header: HeaderHash): void;
38
48
  /**
@@ -56,6 +66,7 @@ export declare class InMemoryStates implements StatesDb<InMemoryState> {
56
66
  /** Insert a full state into the database. */
57
67
  insertInitialState(headerHash: HeaderHash, state: InMemoryState): Promise<Result<OK, StateUpdateError>>;
58
68
  getState(headerHash: HeaderHash): InMemoryState | null;
69
+ commitFinalized(_headers: HeaderHash[]): void;
59
70
  markUnused(header: HeaderHash): void;
60
71
  close(): Promise<void>;
61
72
  }
@@ -1 +1 @@
1
- {"version":3,"file":"states.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database/states.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,KAAK,EAAe,MAAM,kBAAkB,CAAC;AAE/F,OAAO,EAAe,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE3D,0DAA0D;AAC1D,oBAAY,gBAAgB;IAC1B,oDAAoD;IACpD,QAAQ,IAAI;IACZ,iDAAiD;IACjD,MAAM,IAAI;CACX;AAED,wFAAwF;AACxF,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,KAAK;IACrC,qEAAqE;IACrE,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;CACpG;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK;IAC/C,4CAA4C;IAC5C,YAAY,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE/C;;;;OAIG;IACH,iBAAiB,CACf,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,CAAC,EACR,MAAM,EAAE,OAAO,CAAC,KAAK,GAAG,cAAc,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAEzC,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,CAAC,GAAG,IAAI,CAAC;IAEvC,4EAA4E;IAC5E,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAErC;;;;;OAKG;IACH,eAAe,CAAC,IAAI,MAAM,GAAG,IAAI,CAAC;IAElC,6CAA6C;IAC7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,qBAAa,cAAe,YAAW,QAAQ,CAAC,aAAa,CAAC;IAQxC,OAAO,CAAC,QAAQ,CAAC,IAAI;IAPzC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAmE;IACtF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAE3C,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS;IAI1B,OAAO;IAID,iBAAiB,CACrB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,OAAO,CAAC,KAAK,GAAG,cAAc,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAgBlC,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAKhE,6CAA6C;IACvC,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAM7G,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,GAAG,IAAI;IAStD,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAI9B,KAAK;CACZ"}
1
+ {"version":3,"file":"states.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database/states.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,KAAK,EAAe,MAAM,kBAAkB,CAAC;AAE/F,OAAO,EAAe,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE3D,0DAA0D;AAC1D,oBAAY,gBAAgB;IAC1B,oDAAoD;IACpD,QAAQ,IAAI;IACZ,iDAAiD;IACjD,MAAM,IAAI;CACX;AAED,wFAAwF;AACxF,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,KAAK;IACrC,qEAAqE;IACrE,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;CACpG;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK;IAC/C,4CAA4C;IAC5C,YAAY,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE/C;;;;OAIG;IACH,iBAAiB,CACf,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,CAAC,EACR,MAAM,EAAE,OAAO,CAAC,KAAK,GAAG,cAAc,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAEzC,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,CAAC,GAAG,IAAI,CAAC;IAEvC;;;;;;;;OAQG;IACH,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IAE7C,4EAA4E;IAC5E,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAErC;;;;;OAKG;IACH,eAAe,CAAC,IAAI,MAAM,GAAG,IAAI,CAAC;IAElC,6CAA6C;IAC7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,qBAAa,cAAe,YAAW,QAAQ,CAAC,aAAa,CAAC;IAQxC,OAAO,CAAC,QAAQ,CAAC,IAAI;IAPzC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAmE;IACtF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAE3C,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS;IAI1B,OAAO;IAID,iBAAiB,CACrB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,OAAO,CAAC,KAAK,GAAG,cAAc,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAgBlC,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAKhE,6CAA6C;IACvC,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAM7G,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,GAAG,IAAI;IAStD,eAAe,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI;IAI7C,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAI9B,KAAK;CACZ"}
@@ -53,6 +53,9 @@ export class InMemoryStates {
53
53
  }
54
54
  return InMemoryState.copyFrom(this.spec, state, state.intoServicesData());
55
55
  }
56
+ commitFinalized(_headers) {
57
+ // nothing to do: every state is a full, independent copy.
58
+ }
56
59
  markUnused(header) {
57
60
  this.db.delete(header);
58
61
  }
@@ -0,0 +1,117 @@
1
+ import type { HeaderHash } from "#@typeberry/block";
2
+ import type { ValueHash } from "#@typeberry/trie";
3
+ /** The value hashes a single block introduced and stopped referencing. */
4
+ export interface ValueDelta {
5
+ /** Value hashes (non-embedded) that the block started referencing. */
6
+ inserted: ValueHash[];
7
+ /** Value hashes (non-embedded) that the block stopped referencing. */
8
+ removed: ValueHash[];
9
+ }
10
+ /**
11
+ * Synchronous, read-only view of the persisted refcounting state.
12
+ *
13
+ * Both LMDB and fjall offer synchronous reads, so reads can go straight
14
+ * to the backing store. All writes go through `ValueRefsUpdate` batches
15
+ * instead, since persistent backends can only write asynchronously
16
+ * (LMDB transactions, fjall inserts + persist).
17
+ */
18
+ export interface ValueRefsReader {
19
+ /** How many leaves of the finalized-tip state reference the value. Missing keys read as `0`. */
20
+ getFinalizedCount(hash: ValueHash): number;
21
+ /** How many surviving, not-yet-finalized blocks inserted the value. Missing keys read as `0`. */
22
+ getPendingCount(hash: ValueHash): number;
23
+ /** The value delta of a not-yet-finalized block, if known. */
24
+ getDelta(header: HeaderHash): ValueDelta | undefined;
25
+ }
26
+ /**
27
+ * A batch of refcounting mutations produced by a single `ValueRefs` operation.
28
+ *
29
+ * The backend is responsible for applying the batch using its own write
30
+ * primitive - ideally atomically with the state write that triggered it
31
+ * (one LMDB transaction, one fjall persist).
32
+ *
33
+ * Counts are absolute values rather than increments, so applying the same
34
+ * update more than once (e.g. on crash-replay) is harmless.
35
+ *
36
+ * When atomicity is not available, apply in field order and `removeValues`
37
+ * strictly last: a crash after counts are persisted but before values are
38
+ * removed only leaks values, while the opposite order could drop a value
39
+ * the persisted counts still consider referencd.
40
+ */
41
+ export interface ValueRefsUpdate {
42
+ /** New absolute finalized counts. Count `0` means the entry should be removed. */
43
+ finalizedCounts: [ValueHash, number][];
44
+ /** New absolute pending counts. Count `0` means the entry should be removed. */
45
+ pendingCounts: [ValueHash, number][];
46
+ /** Deltas of freshly imported blocks to persist. */
47
+ setDeltas: [HeaderHash, ValueDelta][];
48
+ /** Deltas consumed by finalization or fork pruning. */
49
+ removeDeltas: HeaderHash[];
50
+ /** Values that are no longer referenced and can be removed from the values DB. */
51
+ removeValues: ValueHash[];
52
+ }
53
+ /** `true` if applying the update would not change anything. */
54
+ export declare function isEmptyUpdate(update: ValueRefsUpdate): boolean;
55
+ /**
56
+ * Decides when a content-addressed value can be removed from the values DB.
57
+ *
58
+ * A value is needed as long as some surviving state references it. Surviving
59
+ * states are the finalized tip plus its unfinalized descendants, so we track:
60
+ * - `finalized`: how many leaves in the current finalized-tip state reference V,
61
+ * advanced strictly by replaying finalized blocks' deltas (never on prune);
62
+ * - `pending`: how many surviving, not-yet-finalized blocks inserted V (an
63
+ * over-approximation of unfinalized references).
64
+ *
65
+ * A value is removable exactly when both counts reach zero.
66
+ *
67
+ * This class only makes decisions: every operation reads the current state
68
+ * through `ValueRefsReader` and returns a `ValueRefsUpdate` describing what
69
+ * should change. Nothing is written here - the owning backend applies the
70
+ * update with whatever consistency guarantees it can provide.
71
+ */
72
+ export declare class ValueRefs {
73
+ private readonly reader;
74
+ constructor(reader: ValueRefsReader);
75
+ /** Record values referenced by the genesis / initial finalized state. */
76
+ onInitial(inserted: ValueHash[]): ValueRefsUpdate;
77
+ /**
78
+ * Record a freshly imported, not-yet-finalized block.
79
+ *
80
+ * Importing the same header twice is a no-op, otherwise the second import
81
+ * would double-count `pending` references and pin the values forever.
82
+ */
83
+ onImport(header: HeaderHash, delta: ValueDelta): ValueRefsUpdate;
84
+ /**
85
+ * Apply the value deltas of newly finalized blocks, in finalized (ancestor-first) order.
86
+ *
87
+ * Moves each inserted value from `pending` to `finalized`, drops `finalized`
88
+ * references for removed values, and collects anything that becomes unreferenced.
89
+ */
90
+ commitFinalized(headers: HeaderHash[]): ValueRefsUpdate;
91
+ /**
92
+ * Release the speculative references of a state being discarded.
93
+ *
94
+ * For a header that was still unfinalized (a dead fork) the returned update
95
+ * releases its inserted values, which may become collectable. For an already
96
+ * finalized state the update is empty (check with `isEmptyUpdate`): its delta
97
+ * was consumed on finality and its values are accounted for in `finalized`.
98
+ */
99
+ releaseUnfinalized(header: HeaderHash): ValueRefsUpdate;
100
+ }
101
+ /**
102
+ * In-memory refcounting store, reusable by the in-memory and hybrid states DBs
103
+ * (the hybrids cannot resume from disk anyway, so persisting counts buys nothing).
104
+ *
105
+ * NOTE: `apply` does not touch the values DB - the caller owns it and must
106
+ * handle `update.removeValues` itself.
107
+ */
108
+ export declare class InMemoryValueRefsStore implements ValueRefsReader {
109
+ private readonly finalized;
110
+ private readonly pending;
111
+ private readonly deltas;
112
+ getFinalizedCount(hash: ValueHash): number;
113
+ getPendingCount(hash: ValueHash): number;
114
+ getDelta(header: HeaderHash): ValueDelta | undefined;
115
+ apply(update: ValueRefsUpdate): void;
116
+ }
117
+ //# sourceMappingURL=value-refs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-refs.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database/value-refs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,0EAA0E;AAC1E,MAAM,WAAW,UAAU;IACzB,sEAAsE;IACtE,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,sEAAsE;IACtE,OAAO,EAAE,SAAS,EAAE,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,gGAAgG;IAChG,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3C,iGAAiG;IACjG,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IACzC,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;CACtD;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,eAAe;IAC9B,kFAAkF;IAClF,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC;IACvC,gFAAgF;IAChF,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC;IACrC,oDAAoD;IACpD,SAAS,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC;IACtC,uDAAuD;IACvD,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,kFAAkF;IAClF,YAAY,EAAE,SAAS,EAAE,CAAC;CAC3B;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAQ9D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,SAAS;IACR,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,eAAe;IAEpD,yEAAyE;IACzE,SAAS,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,eAAe;IAQjD;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,GAAG,eAAe;IAYhE;;;;;OAKG;IACH,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,eAAe;IAoBvD;;;;;;;OAOG;IACH,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,eAAe;CAYxD;AA0ED;;;;;;GAMG;AACH,qBAAa,sBAAuB,YAAW,eAAe;IAC5D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA2D;IACrF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2D;IACnF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgE;IAEvF,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM;IAI1C,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM;IAIxC,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS;IAIpD,KAAK,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;CAUrC"}