@fireproof/core 0.8.0-dev → 0.8.0-dev.3

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.
@@ -45,11 +45,10 @@ export class Filesystem extends Base {
45
45
  }
46
46
 
47
47
  async writeHeader (branch, header) {
48
- // console.log('saveHeader', this.isBrowser)
48
+ // console.log('saveHeader fs', header)
49
49
  if (this.config.readonly) return
50
- const pHeader = this.prepareHeader(header)
51
50
  // console.log('writeHeader fs', branch, pHeader)
52
- await writeSync(this.headerFilename(branch), pHeader)
51
+ await writeSync(this.headerFilename(branch), header)
53
52
  }
54
53
 
55
54
  headerFilename (branch = 'main') {
@@ -47,12 +47,11 @@ export class Rest extends Base {
47
47
 
48
48
  async writeHeader (branch, header) {
49
49
  if (this.config.readonly) return
50
- const pHeader = this.prepareHeader(header)
51
50
  // console.log('writeHeader rt', branch, pHeader)
52
51
 
53
52
  const response = await fetch(this.headerURL(branch), {
54
53
  method: 'PUT',
55
- body: pHeader,
54
+ body: header,
56
55
  headers: { 'Content-Type': 'application/json' }
57
56
  })
58
57
  if (!response.ok) throw new Error(`An error occurred: ${response.statusText}`)
@@ -0,0 +1,152 @@
1
+ import * as CBW from '@ipld/car/buffer-writer'
2
+ import * as raw from 'multiformats/codecs/raw'
3
+ import { encrypt, decrypt } from '../crypto.js'
4
+ import { parse } from 'multiformats/link'
5
+ import { sha256 } from 'multiformats/hashes/sha2'
6
+ import * as Block from 'multiformats/block'
7
+ import { Buffer } from 'buffer'
8
+ // @ts-ignore
9
+ import { bf } from 'prolly-trees/utils'
10
+ // @ts-ignore
11
+ import { nocache as cache } from 'prolly-trees/cache'
12
+ const chunker = bf(30)
13
+
14
+ export async function getEmptyLoader () { // unused?
15
+ const theseWriteableBlocks = new VMemoryBlockstore()
16
+ return {
17
+ blocks: theseWriteableBlocks,
18
+ put: async (cid, bytes) => {
19
+ return await theseWriteableBlocks.put(cid, bytes)
20
+ },
21
+ get: async (cid) => {
22
+ const got = await theseWriteableBlocks.get(cid)
23
+ return got.bytes
24
+ }
25
+ }
26
+ }
27
+
28
+ export class VMemoryBlockstore {
29
+ /** @type {Map<string, Uint8Array>} */
30
+ blocks = new Map()
31
+ instanceId = Math.random().toString(36).slice(2)
32
+
33
+ async get (cid) {
34
+ const bytes = this.blocks.get(cid.toString())
35
+ if (!bytes) throw new Error('block not found ' + cid.toString())
36
+ return { cid, bytes }
37
+ }
38
+
39
+ /**
40
+ * @param {any} cid
41
+ * @param {Uint8Array} bytes
42
+ */
43
+ async put (cid, bytes) {
44
+ this.blocks.set(cid.toString(), bytes)
45
+ }
46
+
47
+ * entries () {
48
+ for (const [str, bytes] of this.blocks) {
49
+ yield { cid: parse(str), bytes }
50
+ }
51
+ }
52
+ }
53
+
54
+ export const blocksToCarBlock = async (rootCids, blocks) => {
55
+ // console.log('blocksToCarBlock', rootCids, blocks.constructor.name)
56
+ let size = 0
57
+ if (!Array.isArray(rootCids)) {
58
+ rootCids = [rootCids]
59
+ }
60
+ const headerSize = CBW.headerLength({ roots: rootCids })
61
+ size += headerSize
62
+ if (!Array.isArray(blocks)) {
63
+ blocks = Array.from(blocks.entries())
64
+ }
65
+ for (const { cid, bytes } of blocks) {
66
+ // console.log(cid, bytes)
67
+ size += CBW.blockLength({ cid, bytes })
68
+ }
69
+ const buffer = new Uint8Array(size)
70
+ const writer = await CBW.createWriter(buffer, { headerSize })
71
+
72
+ for (const cid of rootCids) {
73
+ writer.addRoot(cid)
74
+ }
75
+
76
+ for (const { cid, bytes } of blocks) {
77
+ writer.write({ cid, bytes })
78
+ }
79
+ await writer.close()
80
+ return await Block.encode({ value: writer.bytes, hasher: sha256, codec: raw })
81
+ }
82
+
83
+ export const blocksToEncryptedCarBlock = async (innerBlockStoreClockRootCid, blocks, keyMaterial, cids) => {
84
+ const encryptionKey = Buffer.from(keyMaterial, 'hex')
85
+ const encryptedBlocks = []
86
+ const theCids = cids
87
+ // console.trace('blocksToEncryptedCarBlock', blocks)
88
+ // for (const { cid } of blocks.entries()) {
89
+ // theCids.push(cid.toString())
90
+ // }
91
+ // console.log(
92
+ // 'encrypting',
93
+ // theCids.length,
94
+ // 'blocks',
95
+ // theCids.includes(innerBlockStoreClockRootCid.toString()),
96
+ // keyMaterial
97
+ // )
98
+ // console.log('cids', theCids, innerBlockStoreClockRootCid.toString())
99
+ let last
100
+ for await (const block of encrypt({
101
+ cids: theCids,
102
+ get: async (cid) => {
103
+ // console.log('getencrypt', cid)
104
+ const got = blocks.get(cid)
105
+ // console.log('got', got)
106
+ return got.block ? ({ cid, bytes: got.block }) : got
107
+ },
108
+ key: encryptionKey,
109
+ hasher: sha256,
110
+ chunker,
111
+ cache,
112
+ // codec: dagcbor, // should be crypto?
113
+ root: innerBlockStoreClockRootCid
114
+ })) {
115
+ encryptedBlocks.push(block)
116
+ last = block
117
+ }
118
+ // console.log('last', last.cid.toString(), 'for clock', innerBlockStoreClockRootCid.toString())
119
+ const encryptedCar = await blocksToCarBlock(last.cid, encryptedBlocks)
120
+ return encryptedCar
121
+ }
122
+
123
+ // { root, get, key, cache, chunker, hasher }
124
+ const memoizeDecryptedCarBlocks = new Map()
125
+ export const blocksFromEncryptedCarBlock = async (cid, get, keyMaterial) => {
126
+ if (memoizeDecryptedCarBlocks.has(cid.toString())) {
127
+ return memoizeDecryptedCarBlocks.get(cid.toString())
128
+ } else {
129
+ const blocksPromise = (async () => {
130
+ const decryptionKey = Buffer.from(keyMaterial, 'hex')
131
+ // console.log('decrypting', keyMaterial, cid.toString())
132
+ const cids = new Set()
133
+ const decryptedBlocks = []
134
+ for await (const block of decrypt({
135
+ root: cid,
136
+ get,
137
+ key: decryptionKey,
138
+ chunker,
139
+ hasher: sha256,
140
+ cache
141
+ // codec: dagcbor
142
+ })) {
143
+ // console.log('decrypted', block.cid.toString())
144
+ decryptedBlocks.push(block)
145
+ cids.add(block.cid.toString())
146
+ }
147
+ return { blocks: decryptedBlocks, cids }
148
+ })()
149
+ memoizeDecryptedCarBlocks.set(cid.toString(), blocksPromise)
150
+ return blocksPromise
151
+ }
152
+ }
package/src/sync.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import SimplePeer from 'simple-peer'
2
2
  import { parseCID } from './database.js'
3
3
  import { decodeEventBlock } from './clock.js'
4
- import { blocksToCarBlock, blocksToEncryptedCarBlock } from './storage/base.js'
4
+ import { blocksToCarBlock, blocksToEncryptedCarBlock } from './storage/utils.js'
5
5
  import { CarReader } from '@ipld/car'
6
6
 
7
7
  /**
package/src/valet.js CHANGED
@@ -79,16 +79,22 @@ export class Valet {
79
79
  if (this.secondary) {
80
80
  // console.log('getValetBlock secondary', dataCID)
81
81
  try {
82
+ // eslint-disable-next-line
82
83
  const { block, reader } = await this.secondary.getLoaderBlock(dataCID)
84
+ const writeableCarReader = await this.primary.getWriteableCarReader(reader)
85
+ // console.log('getValetBlock secondary', dataCID, block.length)
86
+ // eslint-disable-next-line
83
87
  const cids = new Set()
84
88
  for await (const { cid } of reader.entries()) {
85
89
  // console.log(cid, bytes)
86
90
  cids.add(cid.toString())
87
91
  }
88
- reader.get = reader.gat // some consumers prefer get
92
+ // reader.get = reader.gat // some consumers prefer get
89
93
  // console.log('replicating', reader.root)
90
- reader.lastCid = reader.root.cid
91
- await this.primary.parkCar(reader, [...cids])
94
+ writeableCarReader.lastCid = reader.root.cid
95
+ writeableCarReader.head = []
96
+ await this.primary.parkCar(writeableCarReader, cids).catch(e => console.error('parkCar error', e))
97
+ // console.log('FIX THIS', did)
92
98
  return block
93
99
  } catch (e) {
94
100
  // console.log('getValetBlock secondary error', e)