@steve02081504/fount-p2p 0.0.25 → 0.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/core/bytes_codec.mjs +5 -6
- package/core/composite_key.mjs +0 -79
- package/core/entity_id_parse.mjs +2 -3
- package/core/evfs_logical_path.mjs +2 -3
- package/core/hexIds.mjs +5 -5
- package/core/logical_entity.mjs +3 -4
- package/crypto/channel.mjs +2 -25
- package/crypto/checkpoint_sign.mjs +5 -4
- package/crypto/crypto.mjs +0 -8
- package/crypto/key.mjs +9 -10
- package/dag/canonicalize_row.mjs +1 -1
- package/discovery/advert_peer_hints.mjs +1 -1
- package/discovery/adverts.mjs +7 -12
- package/discovery/bt/index.mjs +3 -11
- package/discovery/bt/peer_hints.mjs +2 -3
- package/discovery/bt/runtime.mjs +1 -1
- package/discovery/index.mjs +14 -14
- package/discovery/lan.mjs +3 -3
- package/discovery/lan_interfaces.mjs +2 -2
- package/discovery/lan_peer_hints.mjs +1 -1
- package/discovery/nostr.mjs +16 -21
- package/federation/entity_key_chain.mjs +5 -24
- package/federation/message_rate_limit.mjs +3 -2
- package/federation/part_query/runtime.mjs +42 -40
- package/files/assemble.mjs +3 -3
- package/files/assemble_stream.mjs +1 -1
- package/files/chunk/fetch.mjs +1 -2
- package/files/chunk/responder.mjs +4 -41
- package/files/chunk/store.mjs +2 -3
- package/files/chunk/verify.mjs +2 -3
- package/files/evfs.mjs +1 -1
- package/files/evfs_ref.mjs +3 -4
- package/files/fetch_fanout.mjs +3 -3
- package/files/manifest/fetch.mjs +2 -3
- package/files/manifest/normalize.mjs +9 -9
- package/files/manifest/pending.mjs +1 -4
- package/files/manifest/public.mjs +8 -8
- package/files/transfer_key.mjs +3 -3
- package/files/transfer_key_registry.mjs +6 -6
- package/governance/branch.mjs +2 -1
- package/governance/join_pow.mjs +7 -5
- package/governance/owner_succession_ballot.mjs +6 -6
- package/index.mjs +2 -2
- package/infra/default_node_dir.mjs +2 -2
- package/infra/priority.mjs +2 -2
- package/link/frame.mjs +2 -3
- package/link/handshake.mjs +6 -6
- package/link/pipe.mjs +1 -2
- package/link/providers/ble_gatt.mjs +1 -9
- package/link/providers/index.mjs +2 -2
- package/link/providers/nostr.mjs +1 -3
- package/link/providers/webrtc.mjs +1 -1
- package/link/rtc/ice_local_hostname.mjs +6 -5
- package/link/rtc/w3c_bridge.mjs +1 -1
- package/link/sdp_fingerprint.mjs +1 -1
- package/mailbox/consumer_registry.mjs +2 -2
- package/mailbox/deliver_or_store.mjs +4 -4
- package/mailbox/parse.mjs +1 -1
- package/mailbox/prune.mjs +2 -2
- package/mailbox/rate.mjs +3 -10
- package/mailbox/store.mjs +7 -7
- package/node/denylist.mjs +38 -38
- package/node/entity_store.mjs +5 -5
- package/node/identity.mjs +7 -8
- package/node/instance.mjs +1 -1
- package/node/log.mjs +1 -1
- package/node/network.mjs +14 -16
- package/node/personal_block.mjs +22 -20
- package/node/reputation_store.mjs +11 -19
- package/node/reputation_sync.mjs +0 -7
- package/node/signaling_config.mjs +1 -1
- package/node/storage_plugins.mjs +2 -2
- package/overlay/index.mjs +1 -1
- package/package.json +1 -1
- package/registries/event_type.mjs +2 -2
- package/registries/room_provider.mjs +2 -2
- package/reputation/engine.mjs +17 -15
- package/schemas/discovery.mjs +5 -5
- package/schemas/federation_pull.mjs +16 -24
- package/schemas/part_query.mjs +4 -4
- package/timeline/verify_remote.mjs +4 -4
- package/transport/group_link_set.mjs +2 -2
- package/transport/ice_servers.mjs +2 -2
- package/transport/link_registry.mjs +6 -18
- package/transport/mesh_keepalive.mjs +1 -1
- package/transport/node_scope/wire.mjs +1 -1
- package/transport/remote_user_room.mjs +13 -15
- package/transport/rtc_connection_budget.mjs +6 -6
- package/transport/runtime_bootstrap.mjs +12 -12
- package/trust_graph/cache.mjs +2 -3
- package/trust_graph/engine.mjs +1 -1
- package/trust_graph/registry.mjs +2 -2
- package/trust_graph/send.mjs +1 -1
- package/utils/async_mutex.mjs +1 -1
- package/wire/ingress.mjs +1 -1
- package/wire/part/fanout.mjs +8 -6
- package/wire/part/ingress.mjs +6 -6
- package/wire/part/query.mjs +3 -3
- package/wire/volatile_signature.mjs +4 -9
package/trust_graph/send.mjs
CHANGED
|
@@ -20,7 +20,7 @@ import trustGraphTunables from './tunables.json' with { type: 'json' }
|
|
|
20
20
|
* @returns {Promise<boolean>} 是否已发送
|
|
21
21
|
*/
|
|
22
22
|
export async function sendToNode(username, targetNodeHash, actionName, payload, graph) {
|
|
23
|
-
const target = normalizeHex64(targetNodeHash)
|
|
23
|
+
const target = normalizeHex64(targetNodeHash)
|
|
24
24
|
if (!isHex64(target)) return false
|
|
25
25
|
|
|
26
26
|
// 已直连 peer 不经 trust-graph scope 也应能收发 node scope action(非成员 CAS chunk / follow hint 等)
|
package/utils/async_mutex.mjs
CHANGED
|
@@ -39,7 +39,7 @@ function releaseMutex(lockKey, state) {
|
|
|
39
39
|
* @template T
|
|
40
40
|
*/
|
|
41
41
|
export async function withAsyncMutex(key, criticalSection) {
|
|
42
|
-
const lockKey =
|
|
42
|
+
const lockKey = key
|
|
43
43
|
const state = mutexState(lockKey)
|
|
44
44
|
return new Promise((resolve, reject) => {
|
|
45
45
|
/**
|
package/wire/ingress.mjs
CHANGED
|
@@ -46,6 +46,6 @@ export function isSignedDagEventRow(event) {
|
|
|
46
46
|
*/
|
|
47
47
|
export function extractInboundSignedEvent(payload, groupId) {
|
|
48
48
|
if (!isSignedDagEventRow(payload)) return null
|
|
49
|
-
if (payload.groupId &&
|
|
49
|
+
if (payload.groupId && payload.groupId !== groupId) return null
|
|
50
50
|
return payload
|
|
51
51
|
}
|
package/wire/part/fanout.mjs
CHANGED
|
@@ -61,10 +61,11 @@ export function partInvokeErrorMessages(results) {
|
|
|
61
61
|
/**
|
|
62
62
|
* 向 trust-graph top-K 扇出 part_invoke,收集 part_invoke_response。
|
|
63
63
|
* 调用方须已挂载 `attachPartWire`(否则收不到 response)。
|
|
64
|
+
* `timeoutMs` 端到端约束:fanout 挂起(discoverRoute / stuck send)也不阻塞返回。
|
|
64
65
|
* @param {string} username trust graph 上下文
|
|
65
66
|
* @param {string} partpath part 路径
|
|
66
67
|
* @param {PartInvoke} invoke 调用体
|
|
67
|
-
* @param {number} [timeoutMs=2500]
|
|
68
|
+
* @param {number} [timeoutMs=2500] 端到端超时
|
|
68
69
|
* @param {number} [maxResponses=6] 最多响应数
|
|
69
70
|
* @returns {Promise<PartInvokeResponse[]>} 邻居 PartInvokeResponse(含 error)
|
|
70
71
|
*/
|
|
@@ -85,15 +86,16 @@ export async function collectPartInvokeResponses(username, partpath, invoke, tim
|
|
|
85
86
|
pendingPartInvoke.set(requestId, { responses, finish, maxResponses, respondedPeers: new Set() })
|
|
86
87
|
})
|
|
87
88
|
|
|
88
|
-
|
|
89
|
+
// 勿 await fanout:否则 timeout 已触发也要等扇出 settle(#13)
|
|
90
|
+
void requireTrustGraphProvider(DEFAULT_TRUST_GRAPH_OWNER).fanoutToTopNodes(
|
|
89
91
|
username,
|
|
90
92
|
'part_invoke',
|
|
91
93
|
buildPartInvokePayload(partpath, invoke, nodeHash, requestId),
|
|
92
94
|
maxResponses,
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
).then(sent => {
|
|
96
|
+
const pending = pendingPartInvoke.get(requestId)
|
|
97
|
+
if (pending && sent === 0) pending.finish()
|
|
98
|
+
}, () => { /* pending wait 超时负责 settle */ })
|
|
97
99
|
|
|
98
100
|
return waitForResponses
|
|
99
101
|
}
|
package/wire/part/ingress.mjs
CHANGED
|
@@ -21,15 +21,15 @@ import { handleIncomingPartInvokeResponse } from './pending.mjs'
|
|
|
21
21
|
* @returns {object | null} 白名单字段
|
|
22
22
|
*/
|
|
23
23
|
function parsePartTimelinePut(data, partpath) {
|
|
24
|
-
const timelineEntityHash = String(data.timelineEntityHash || '')
|
|
24
|
+
const timelineEntityHash = String(data.timelineEntityHash || '')
|
|
25
25
|
if (!timelineEntityHash || !isPlainObject(data.event)) return null
|
|
26
26
|
return {
|
|
27
27
|
type: 'part_timeline_put',
|
|
28
28
|
partpath,
|
|
29
29
|
timelineEntityHash,
|
|
30
30
|
event: data.event,
|
|
31
|
-
...data.nodeHash ? { nodeHash: String(data.nodeHash)
|
|
32
|
-
...data.groupId ? { groupId: String(data.groupId)
|
|
31
|
+
...data.nodeHash ? { nodeHash: String(data.nodeHash) } : {},
|
|
32
|
+
...data.groupId ? { groupId: String(data.groupId) } : {},
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -60,8 +60,8 @@ async function dispatchPartInvoke(wireContext, payload) {
|
|
|
60
60
|
if (!partpath || !isPlainObject(invoke)) return null
|
|
61
61
|
return dispatchRpcInbound({
|
|
62
62
|
replicaUsername: wireContext.replicaUsername,
|
|
63
|
-
requesterNodeHash: payload.peerId
|
|
64
|
-
groupId: payload.groupId
|
|
63
|
+
requesterNodeHash: payload.peerId || null,
|
|
64
|
+
groupId: payload.groupId || undefined,
|
|
65
65
|
peerId: payload.peerId,
|
|
66
66
|
}, {
|
|
67
67
|
type: 'part_invoke',
|
|
@@ -93,7 +93,7 @@ export function attachPartWire(wireContext, wire, options = {}) {
|
|
|
93
93
|
if (!message) return
|
|
94
94
|
void dispatchDeliveryInbound({
|
|
95
95
|
replicaUsername: wireContext.replicaUsername,
|
|
96
|
-
requesterNodeHash: peerId
|
|
96
|
+
requesterNodeHash: peerId || null,
|
|
97
97
|
}, message)
|
|
98
98
|
},
|
|
99
99
|
/**
|
package/wire/part/query.mjs
CHANGED
|
@@ -48,11 +48,11 @@ export function attachPartQueryWire(wireContext, wire, dependencies = {}) {
|
|
|
48
48
|
const request = parsePartQueryReq(data)
|
|
49
49
|
if (!request) return
|
|
50
50
|
if (!state.takeDedupe(request.requestId)) return
|
|
51
|
-
const source =
|
|
51
|
+
const source = peerId || request.originNodeHash
|
|
52
52
|
if (source && !consumeWireRateBucket(`part_query:${source}`, {
|
|
53
53
|
maxCount: partQueryTunables.ratePerSourcePerMin,
|
|
54
54
|
})) return
|
|
55
|
-
void processIncomingPartQueryRequest(wireContext, wire, request,
|
|
55
|
+
void processIncomingPartQueryRequest(wireContext, wire, request, peerId, deps)
|
|
56
56
|
},
|
|
57
57
|
/**
|
|
58
58
|
* @param {unknown} data part_query_res 载荷
|
|
@@ -61,7 +61,7 @@ export function attachPartQueryWire(wireContext, wire, dependencies = {}) {
|
|
|
61
61
|
part_query_res(data, peerId) {
|
|
62
62
|
const response = parsePartQueryRes(data)
|
|
63
63
|
if (!response) return
|
|
64
|
-
handleIncomingPartQueryResponse(response,
|
|
64
|
+
handleIncomingPartQueryResponse(response, peerId, deps)
|
|
65
65
|
},
|
|
66
66
|
})
|
|
67
67
|
}
|
|
@@ -28,10 +28,9 @@ export function boundStreamSlices(slices) {
|
|
|
28
28
|
* @returns {Uint8Array} 验签消息字节
|
|
29
29
|
*/
|
|
30
30
|
export function streamChunkSignBytes(pendingStreamId, chunkSeq, slices) {
|
|
31
|
-
const streamId = String(pendingStreamId ?? '')
|
|
32
31
|
const sequence = Number.isFinite(Number(chunkSeq)) ? String(chunkSeq) : '0'
|
|
33
32
|
const body = JSON.stringify(slices ?? [])
|
|
34
|
-
return new TextEncoder().encode(`${CHUNK_DOMAIN}\0${
|
|
33
|
+
return new TextEncoder().encode(`${CHUNK_DOMAIN}\0${pendingStreamId}\0${sequence}\0${body}`)
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
/**
|
|
@@ -51,11 +50,9 @@ export async function signStreamSignatureHex(bytes, secretKey) {
|
|
|
51
50
|
* @returns {Promise<boolean>} 验签是否通过
|
|
52
51
|
*/
|
|
53
52
|
export async function verifyStreamSignatureHex(bytes, signatureHex, publicKeyHex) {
|
|
54
|
-
|
|
55
|
-
const publicKey = String(publicKeyHex || '').trim().toLowerCase()
|
|
56
|
-
if (!isSignatureHex128(signature) || !isHex64(publicKey)) return false
|
|
53
|
+
if (!isSignatureHex128(signatureHex) || !isHex64(publicKeyHex)) return false
|
|
57
54
|
try {
|
|
58
|
-
return await verify(Buffer.from(
|
|
55
|
+
return await verify(Buffer.from(signatureHex, 'hex'), bytes, Buffer.from(publicKeyHex, 'hex'))
|
|
59
56
|
}
|
|
60
57
|
catch {
|
|
61
58
|
return false
|
|
@@ -69,8 +66,6 @@ export async function verifyStreamSignatureHex(bytes, signatureHex, publicKeyHex
|
|
|
69
66
|
* @returns {{ publicKey: Uint8Array, secretKey: Uint8Array }} 密钥对
|
|
70
67
|
*/
|
|
71
68
|
export function streamKeyPairFromUserSeed(username, seedMaterial) {
|
|
72
|
-
const
|
|
73
|
-
const material = String(seedMaterial ?? '')
|
|
74
|
-
const seed = createHash('sha256').update(`fount-stream-sign\0${user}\0${material}`).digest()
|
|
69
|
+
const seed = createHash('sha256').update(`fount-stream-sign\0${username}\0${seedMaterial}`).digest()
|
|
75
70
|
return keyPairFromSeed(seed)
|
|
76
71
|
}
|