keri-ts 2.0.1 → 2.1.0
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/esm/keri/npm/src/acdc/chaining.js +223 -89
- package/esm/keri/npm/src/acdc/observing.js +2 -2
- package/esm/keri/npm/src/acdc/regbasing.js +20 -29
- package/esm/keri/npm/src/acdc/regengine.js +4 -6
- package/esm/keri/npm/src/acdc/registering.js +13 -10
- package/esm/keri/npm/src/acdc/registraring.js +4 -9
- package/esm/keri/npm/src/acdc/salting.js +127 -25
- package/esm/keri/npm/src/acdc/unblinding.js +2 -4
- package/esm/keri/npm/src/app/bootstrap/oobiery.js +1 -1
- package/esm/keri/npm/src/app/credentials/root-replicating.js +123 -0
- package/esm/keri/npm/src/app/credentials/verifying.js +12 -3
- package/esm/keri/npm/src/app/delivery/forwarding.js +49 -7
- package/esm/keri/npm/src/app/exchanges/exchanging.js +11 -12
- package/esm/keri/npm/src/app/identity/configing.js +17 -43
- package/esm/keri/npm/src/app/identity/habbing.js +54 -35
- package/esm/keri/npm/src/app/identity/keeping.js +1 -1
- package/esm/keri/npm/src/app/identity/lmdb-habery.js +12 -0
- package/esm/keri/npm/src/app/ipex/ipex-graph.js +7 -70
- package/esm/keri/npm/src/app/ipex/ipex-grouping.js +8 -5
- package/esm/keri/npm/src/app/ipex/ipex-v2.js +21 -5
- package/esm/keri/npm/src/app/ipex/ipexing.js +1 -1
- package/esm/keri/npm/src/app/mailbox/mailboxing.js +5 -9
- package/esm/keri/npm/src/app/multisig/group-members.js +14 -0
- package/esm/keri/npm/src/app/multisig/grouping.js +4 -3
- package/esm/keri/npm/src/app/multisig/multisig-workflows.js +7 -2
- package/esm/keri/npm/src/app/notifications/notifying.js +5 -9
- package/esm/keri/npm/src/app/protocol/protocol-processing.js +35 -3
- package/esm/keri/npm/src/app/queries/witness-inquisitor.js +2 -2
- package/esm/keri/npm/src/app/runtime/agent-runtime.js +7 -10
- package/esm/keri/npm/src/app/transport/byte-source.js +6 -42
- package/esm/keri/npm/src/app/transport/cesr-egress.js +77 -13
- package/esm/keri/npm/src/app/transport/file-bytes.js +41 -0
- package/esm/keri/npm/src/app/transport/http-messenger.js +14 -9
- package/esm/keri/npm/src/app/transport/message-source.js +1 -1
- package/esm/keri/npm/src/app/transport/messengering.js +3 -4
- package/esm/keri/npm/src/app/transport/node-http-client.js +21 -0
- package/esm/keri/npm/src/app/transport/tcp-dialer.js +14 -0
- package/esm/keri/npm/src/app/witness/receipt-client.js +2 -2
- package/esm/keri/npm/src/cli/common/context.js +2 -2
- package/esm/keri/npm/src/cli/common/existing.js +3 -5
- package/esm/keri/npm/src/cli/credentials/ipex.js +2 -1
- package/esm/keri/npm/src/cli/endpoints/oobi-clean.js +4 -3
- package/esm/keri/npm/src/cli/endpoints/oobi.js +2 -2
- package/esm/keri/npm/src/cli/identity/challenge.js +2 -2
- package/esm/keri/npm/src/cli/identity/incept.js +2 -2
- package/esm/keri/npm/src/cli/identity/init.js +4 -3
- package/esm/keri/npm/src/cli/identity/interact.js +2 -2
- package/esm/keri/npm/src/cli/identity/rotate.js +2 -2
- package/esm/keri/npm/src/cli/messaging/exchange.js +2 -2
- package/esm/keri/npm/src/cli/messaging/multisig.js +61 -3
- package/esm/keri/npm/src/cli/tools/annotate.js +2 -1
- package/esm/keri/npm/src/cli/tools/benchmark.js +2 -1
- package/esm/keri/npm/src/cli/tools/db-dump.js +1 -4
- package/esm/keri/npm/src/core/bytes.js +9 -0
- package/esm/keri/npm/src/core/kel/delegation-ancestry.js +92 -0
- package/esm/keri/npm/src/core/kel/eventing.js +1 -2
- package/esm/keri/npm/src/core/kel/kever.js +11 -9
- package/esm/keri/npm/src/core/mailbox/kram-policy.js +2 -3
- package/esm/keri/npm/src/core/mailbox/kram-pruning.js +15 -22
- package/esm/keri/npm/src/core/mailbox/kram-staging.js +2 -2
- package/esm/keri/npm/src/core/routing.js +2 -2
- package/esm/keri/npm/src/db/basing.js +149 -203
- package/esm/keri/npm/src/db/core/dber.js +1062 -0
- package/esm/keri/npm/src/db/core/index.js +4 -2
- package/esm/keri/npm/src/db/core/lmdb-opener.js +30 -0
- package/esm/keri/npm/src/db/core/lmdber.js +199 -1067
- package/esm/keri/npm/src/db/core/memstore.js +532 -0
- package/esm/keri/npm/src/db/core/path-manager.js +109 -223
- package/esm/keri/npm/src/db/core/store-owner.js +104 -0
- package/esm/keri/npm/src/db/core/webdber.js +252 -0
- package/esm/keri/npm/src/db/escrowing.js +2 -2
- package/esm/keri/npm/src/db/exchange/exchange-nests.js +3 -2
- package/esm/keri/npm/src/db/keeping.js +27 -121
- package/esm/keri/npm/src/db/koming.js +1 -1
- package/esm/keri/npm/src/db/lmdb-stores.js +68 -0
- package/esm/keri/npm/src/db/lmdb.js +6 -0
- package/esm/keri/npm/src/db/mailbox/mailboxing.js +12 -65
- package/esm/keri/npm/src/db/noting.js +11 -55
- package/esm/keri/npm/src/db/reger.js +43 -105
- package/esm/keri/npm/src/db/replay/witness-replay.js +2 -20
- package/esm/keri/npm/src/db/subing.js +1 -1
- package/esm/keri/npm/src/npm/db-lmdb.js +3 -0
- package/esm/keri/npm/src/npm/runtime-node.js +3 -0
- package/esm/keri/npm/src/runtime/index.js +9 -10
- package/esm/keri/npm/src/runtime/node.js +14 -0
- package/esm/keri/npm/src/vdr/eventing.js +1 -1
- package/esm/keri/npm/src/vdr/tel-publication.js +3 -3
- package/esm/keri/npm/src/version.js +2 -2
- package/package.json +11 -4
- package/types/acdc/chaining.d.ts +56 -6
- package/types/acdc/chaining.d.ts.map +1 -1
- package/types/acdc/regbasing.d.ts +7 -6
- package/types/acdc/regbasing.d.ts.map +1 -1
- package/types/acdc/regengine.d.ts.map +1 -1
- package/types/acdc/registering.d.ts +8 -4
- package/types/acdc/registering.d.ts.map +1 -1
- package/types/acdc/registraring.d.ts.map +1 -1
- package/types/acdc/salting.d.ts +53 -6
- package/types/acdc/salting.d.ts.map +1 -1
- package/types/acdc/unblinding.d.ts.map +1 -1
- package/types/app/credentials/root-replicating.d.ts +85 -0
- package/types/app/credentials/root-replicating.d.ts.map +1 -0
- package/types/app/credentials/verifying.d.ts +2 -1
- package/types/app/credentials/verifying.d.ts.map +1 -1
- package/types/app/delivery/forwarding.d.ts +10 -0
- package/types/app/delivery/forwarding.d.ts.map +1 -1
- package/types/app/exchanges/exchanging.d.ts +2 -0
- package/types/app/exchanges/exchanging.d.ts.map +1 -1
- package/types/app/identity/configing.d.ts +7 -5
- package/types/app/identity/configing.d.ts.map +1 -1
- package/types/app/identity/habbing.d.ts +23 -5
- package/types/app/identity/habbing.d.ts.map +1 -1
- package/types/app/identity/keeping.d.ts +1 -1
- package/types/app/identity/lmdb-habery.d.ts +6 -0
- package/types/app/identity/lmdb-habery.d.ts.map +1 -0
- package/types/app/ipex/ipex-graph.d.ts +4 -4
- package/types/app/ipex/ipex-graph.d.ts.map +1 -1
- package/types/app/ipex/ipex-grouping.d.ts.map +1 -1
- package/types/app/ipex/ipex-v2.d.ts +11 -2
- package/types/app/ipex/ipex-v2.d.ts.map +1 -1
- package/types/app/ipex/ipexing.d.ts +3 -0
- package/types/app/ipex/ipexing.d.ts.map +1 -1
- package/types/app/mailbox/mailboxing.d.ts +1 -1
- package/types/app/mailbox/mailboxing.d.ts.map +1 -1
- package/types/app/multisig/group-members.d.ts +9 -0
- package/types/app/multisig/group-members.d.ts.map +1 -1
- package/types/app/multisig/grouping.d.ts.map +1 -1
- package/types/app/multisig/multisig-workflows.d.ts +2 -1
- package/types/app/multisig/multisig-workflows.d.ts.map +1 -1
- package/types/app/notifications/notifying.d.ts +1 -1
- package/types/app/notifications/notifying.d.ts.map +1 -1
- package/types/app/protocol/parsering.d.ts +3 -1
- package/types/app/protocol/parsering.d.ts.map +1 -1
- package/types/app/protocol/protocol-processing.d.ts +2 -0
- package/types/app/protocol/protocol-processing.d.ts.map +1 -1
- package/types/app/runtime/agent-runtime.d.ts +7 -0
- package/types/app/runtime/agent-runtime.d.ts.map +1 -1
- package/types/app/transport/byte-source.d.ts +13 -10
- package/types/app/transport/byte-source.d.ts.map +1 -1
- package/types/app/transport/cesr-egress.d.ts +21 -7
- package/types/app/transport/cesr-egress.d.ts.map +1 -1
- package/types/app/transport/file-bytes.d.ts +11 -0
- package/types/app/transport/file-bytes.d.ts.map +1 -0
- package/types/app/transport/http-client.d.ts +3 -0
- package/types/app/transport/http-client.d.ts.map +1 -1
- package/types/app/transport/http-messenger.d.ts +15 -10
- package/types/app/transport/http-messenger.d.ts.map +1 -1
- package/types/app/transport/message-source.d.ts +1 -1
- package/types/app/transport/messengering.d.ts +2 -2
- package/types/app/transport/messengering.d.ts.map +1 -1
- package/types/app/transport/node-http-client.d.ts +10 -0
- package/types/app/transport/node-http-client.d.ts.map +1 -0
- package/types/app/transport/tcp-dialer.d.ts +21 -0
- package/types/app/transport/tcp-dialer.d.ts.map +1 -0
- package/types/cli/common/existing.d.ts.map +1 -1
- package/types/cli/credentials/ipex.d.ts.map +1 -1
- package/types/cli/endpoints/oobi-clean.d.ts.map +1 -1
- package/types/cli/identity/init.d.ts.map +1 -1
- package/types/cli/index.d.ts +1 -1
- package/types/cli/index.d.ts.map +1 -1
- package/types/cli/messaging/multisig.d.ts +10 -1
- package/types/cli/messaging/multisig.d.ts.map +1 -1
- package/types/cli/tools/annotate.d.ts.map +1 -1
- package/types/cli/tools/benchmark.d.ts.map +1 -1
- package/types/cli/tools/db-dump.d.ts.map +1 -1
- package/types/core/bytes.d.ts +2 -0
- package/types/core/bytes.d.ts.map +1 -1
- package/types/core/kel/delegation-ancestry.d.ts +41 -0
- package/types/core/kel/delegation-ancestry.d.ts.map +1 -0
- package/types/core/kel/eventing.d.ts.map +1 -1
- package/types/core/kel/kever.d.ts +5 -4
- package/types/core/kel/kever.d.ts.map +1 -1
- package/types/core/mailbox/kram-policy.d.ts.map +1 -1
- package/types/core/mailbox/kram-pruning.d.ts +1 -3
- package/types/core/mailbox/kram-pruning.d.ts.map +1 -1
- package/types/db/basing.d.ts +14 -23
- package/types/db/basing.d.ts.map +1 -1
- package/types/db/core/dber.d.ts +505 -0
- package/types/db/core/dber.d.ts.map +1 -0
- package/types/db/core/index.d.ts +4 -2
- package/types/db/core/index.d.ts.map +1 -1
- package/types/db/core/lmdb-opener.d.ts +17 -0
- package/types/db/core/lmdb-opener.d.ts.map +1 -0
- package/types/db/core/lmdber.d.ts +60 -383
- package/types/db/core/lmdber.d.ts.map +1 -1
- package/types/db/core/memstore.d.ts +129 -0
- package/types/db/core/memstore.d.ts.map +1 -0
- package/types/db/core/path-manager.d.ts +22 -45
- package/types/db/core/path-manager.d.ts.map +1 -1
- package/types/db/core/store-owner.d.ts +59 -0
- package/types/db/core/store-owner.d.ts.map +1 -0
- package/types/db/core/webdber.d.ts +127 -0
- package/types/db/core/webdber.d.ts.map +1 -0
- package/types/db/escrowing.d.ts +3 -3
- package/types/db/escrowing.d.ts.map +1 -1
- package/types/db/exchange/exchange-nests.d.ts.map +1 -1
- package/types/db/keeping.d.ts +9 -23
- package/types/db/keeping.d.ts.map +1 -1
- package/types/db/koming.d.ts +7 -8
- package/types/db/koming.d.ts.map +1 -1
- package/types/db/lmdb-stores.d.ts +45 -0
- package/types/db/lmdb-stores.d.ts.map +1 -0
- package/types/db/lmdb.d.ts +7 -0
- package/types/db/lmdb.d.ts.map +1 -0
- package/types/db/mailbox/mailboxing.d.ts +7 -21
- package/types/db/mailbox/mailboxing.d.ts.map +1 -1
- package/types/db/noting.d.ts +7 -12
- package/types/db/noting.d.ts.map +1 -1
- package/types/db/reger.d.ts +7 -11
- package/types/db/reger.d.ts.map +1 -1
- package/types/db/replay/witness-replay.d.ts +0 -2
- package/types/db/replay/witness-replay.d.ts.map +1 -1
- package/types/db/subing.d.ts +24 -25
- package/types/db/subing.d.ts.map +1 -1
- package/types/npm/db-lmdb.d.ts +4 -0
- package/types/npm/db-lmdb.d.ts.map +1 -0
- package/types/npm/runtime-node.d.ts +4 -0
- package/types/npm/runtime-node.d.ts.map +1 -0
- package/types/runtime/index.d.ts +9 -10
- package/types/runtime/index.d.ts.map +1 -1
- package/types/runtime/node.d.ts +15 -0
- package/types/runtime/node.d.ts.map +1 -0
- package/types/version.d.ts +2 -2
- package/esm/keri/npm/src/acdc/relating.js +0 -59
- package/esm/keri/npm/src/db/baser-defaults.js +0 -11
- package/types/acdc/relating.d.ts +0 -21
- package/types/acdc/relating.d.ts.map +0 -1
- package/types/db/baser-defaults.d.ts +0 -5
- package/types/db/baser-defaults.d.ts.map +0 -1
|
@@ -3,7 +3,7 @@ import { OOBI_MAILBOX_TOPIC, OOBI_REQUEST_ROUTE, oobiRequestExn } from "../../ap
|
|
|
3
3
|
import { sendExchangeMessage } from "../../app/exchanges/exchange-messaging.js";
|
|
4
4
|
import { enqueueOobi, runAgentRuntimeUntil, runtimeOobiConverged } from "../../app/runtime/agent-runtime.js";
|
|
5
5
|
import { systemClock } from "../../app/runtime/runtime-clock.js";
|
|
6
|
-
import {
|
|
6
|
+
import { NodeHttpClient } from "../../app/transport/node-http-client.js";
|
|
7
7
|
import { ValidationError } from "../../core/errors.js";
|
|
8
8
|
import { EndpointRoles, isEndpointRole } from "../../core/roles.js";
|
|
9
9
|
import { parseBooleanOption, parseStringOption } from "../common/parsing.js";
|
|
@@ -191,7 +191,7 @@ export function* oobiRequestCommand(args) {
|
|
|
191
191
|
skipSignator: false,
|
|
192
192
|
}, function* ({ hby, hab }) {
|
|
193
193
|
const exn = oobiRequestExn(hab, recipient, url);
|
|
194
|
-
const { serder } = yield* sendExchangeMessage(hby, hab, new
|
|
194
|
+
const { serder } = yield* sendExchangeMessage(hby, hab, new NodeHttpClient(), systemClock, {
|
|
195
195
|
dest: recipient,
|
|
196
196
|
route: OOBI_REQUEST_ROUTE,
|
|
197
197
|
topic: OOBI_MAILBOX_TOPIC,
|
|
@@ -5,7 +5,7 @@ import { Organizer } from "../../app/identity/organizing.js";
|
|
|
5
5
|
import { isLocalGroupHab } from "../../app/multisig/group-members.js";
|
|
6
6
|
import { runAgentRuntime } from "../../app/runtime/agent-runtime.js";
|
|
7
7
|
import { systemClock } from "../../app/runtime/runtime-clock.js";
|
|
8
|
-
import {
|
|
8
|
+
import { NodeHttpClient } from "../../app/transport/node-http-client.js";
|
|
9
9
|
import { ValidationError } from "../../core/errors.js";
|
|
10
10
|
import { parseBooleanOption, parseIntegerOption, parseNumberOption, parseStringOption } from "../common/parsing.js";
|
|
11
11
|
import { withAgentRuntime, withExistingHab } from "../common/context.js";
|
|
@@ -62,7 +62,7 @@ export function* challengeRespondCommand(args) {
|
|
|
62
62
|
throw new ValidationError("Challenge respond does not coordinate group approval. Select the responding member alias.");
|
|
63
63
|
}
|
|
64
64
|
const payload = { words };
|
|
65
|
-
const { serder } = yield* sendExchangeMessage(hby, hab, new
|
|
65
|
+
const { serder } = yield* sendExchangeMessage(hby, hab, new NodeHttpClient(), systemClock, {
|
|
66
66
|
dest: recipient,
|
|
67
67
|
route: CHALLENGE_RESPONSE_ROUTE,
|
|
68
68
|
topic: "challenge",
|
|
@@ -3,7 +3,7 @@ import { resolveBootstrap } from "../../app/bootstrap/bootstrapping.js";
|
|
|
3
3
|
import { createProtocolProcessor } from "../../app/protocol/protocol-processing.js";
|
|
4
4
|
import { createAgentRuntime, runAgentRuntimeUntil, } from "../../app/runtime/agent-runtime.js";
|
|
5
5
|
import { systemClock } from "../../app/runtime/runtime-clock.js";
|
|
6
|
-
import {
|
|
6
|
+
import { NodeHttpClient } from "../../app/transport/node-http-client.js";
|
|
7
7
|
import { ValidationError } from "../../core/errors.js";
|
|
8
8
|
import { assertBootstrapComplete } from "../common/bootstrap.js";
|
|
9
9
|
import { createConfiger } from "../../app/identity/configing.js";
|
|
@@ -50,7 +50,7 @@ function mergeWithFile(args) {
|
|
|
50
50
|
*/
|
|
51
51
|
export function* inceptCommand(args) {
|
|
52
52
|
// Select one HTTP implementation for all work owned by this command.
|
|
53
|
-
const http = new
|
|
53
|
+
const http = new NodeHttpClient();
|
|
54
54
|
const inceptArgs = {
|
|
55
55
|
name: parseStringOption(args.name, "name"),
|
|
56
56
|
base: parseStringOption(args.base, "base"),
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Encrypter } from "cesr-ts";
|
|
2
2
|
import { resolveBootstrap } from "../../app/bootstrap/bootstrapping.js";
|
|
3
3
|
import { createConfiger } from "../../app/identity/configing.js";
|
|
4
|
-
import { branToSeedAeid
|
|
5
|
-
import {
|
|
4
|
+
import { branToSeedAeid } from "../../app/identity/habbing.js";
|
|
5
|
+
import { createHabery } from "../../app/identity/lmdb-habery.js";
|
|
6
|
+
import { NodeHttpClient } from "../../app/transport/node-http-client.js";
|
|
6
7
|
import { ValidationError } from "../../core/errors.js";
|
|
7
8
|
import { assertBootstrapComplete } from "../common/bootstrap.js";
|
|
8
9
|
import { parseBooleanOption, parseStringOption } from "../common/parsing.js";
|
|
@@ -75,7 +76,7 @@ export function* initCommand(args) {
|
|
|
75
76
|
seed,
|
|
76
77
|
salt: initArgs.salt,
|
|
77
78
|
});
|
|
78
|
-
assertBootstrapComplete(yield* resolveBootstrap(hby, new
|
|
79
|
+
assertBootstrapComplete(yield* resolveBootstrap(hby, new NodeHttpClient()));
|
|
79
80
|
created = { keystore: hby.ks.path, database: hby.db.path, aeid: hby.mgr.aeid };
|
|
80
81
|
}
|
|
81
82
|
catch (error) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createProtocolProcessor } from "../../app/protocol/protocol-processing.js";
|
|
2
2
|
import { systemClock } from "../../app/runtime/runtime-clock.js";
|
|
3
|
-
import {
|
|
3
|
+
import { NodeHttpClient } from "../../app/transport/node-http-client.js";
|
|
4
4
|
import { isLocalGroupHab } from "../../app/multisig/group-members.js";
|
|
5
5
|
import { Receiptor, WitnessReceiptor } from "../../app/witness/receipting.js";
|
|
6
6
|
import { ValidationError } from "../../core/errors.js";
|
|
@@ -19,7 +19,7 @@ import { resolveWitnessAuths } from "../common/witness-auth.js";
|
|
|
19
19
|
*/
|
|
20
20
|
export function* interactCommand(args) {
|
|
21
21
|
// Select one HTTP implementation for all work owned by this command.
|
|
22
|
-
const http = new
|
|
22
|
+
const http = new NodeHttpClient();
|
|
23
23
|
const interactArgs = {
|
|
24
24
|
name: parseStringOption(args.name, "name"),
|
|
25
25
|
base: parseStringOption(args.base, "base"),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createProtocolProcessor } from "../../app/protocol/protocol-processing.js";
|
|
2
2
|
import { systemClock } from "../../app/runtime/runtime-clock.js";
|
|
3
|
-
import {
|
|
3
|
+
import { NodeHttpClient } from "../../app/transport/node-http-client.js";
|
|
4
4
|
import { createAgentRuntime, runAgentRuntimeUntil, } from "../../app/runtime/agent-runtime.js";
|
|
5
5
|
import { ValidationError } from "../../core/errors.js";
|
|
6
6
|
import { resolveDelegationCommunicationHab } from "../../app/identity/delegating.js";
|
|
@@ -59,7 +59,7 @@ function difference(left, right) {
|
|
|
59
59
|
*/
|
|
60
60
|
export function* rotateCommand(args, { witnessAuths } = {}) {
|
|
61
61
|
// Select one HTTP implementation for all work owned by this command.
|
|
62
|
-
const http = new
|
|
62
|
+
const http = new NodeHttpClient();
|
|
63
63
|
const rotateArgs = {
|
|
64
64
|
name: parseStringOption(args.name, "name"),
|
|
65
65
|
base: parseStringOption(args.base, "base"),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { sendExchangeMessage } from "../../app/exchanges/exchange-messaging.js";
|
|
2
2
|
import { isLocalGroupHab } from "../../app/multisig/group-members.js";
|
|
3
3
|
import { systemClock } from "../../app/runtime/runtime-clock.js";
|
|
4
|
-
import {
|
|
4
|
+
import { NodeHttpClient } from "../../app/transport/node-http-client.js";
|
|
5
5
|
import { ValidationError } from "../../core/errors.js";
|
|
6
6
|
import { withExistingHab } from "../common/context.js";
|
|
7
7
|
import { parseBooleanOption, parseExnDataItems, parseStringListOption, parseStringOption } from "../common/parsing.js";
|
|
@@ -53,7 +53,7 @@ export function* exchangeSendCommand(args) {
|
|
|
53
53
|
if (isLocalGroupHab(hby, hab)) {
|
|
54
54
|
throw new ValidationError("Generic exchange send does not coordinate group approval. Use a member alias or the matching group IPEX workflow.");
|
|
55
55
|
}
|
|
56
|
-
const { serder } = yield* sendExchangeMessage(hby, hab, new
|
|
56
|
+
const { serder } = yield* sendExchangeMessage(hby, hab, new NodeHttpClient(), systemClock, {
|
|
57
57
|
dest: recipient,
|
|
58
58
|
route,
|
|
59
59
|
topic: commandArgs.topic,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { action, spawn } from "effection";
|
|
2
|
+
import { resealRegistryRoots, } from "../../app/credentials/root-replicating.js";
|
|
2
3
|
import { resolveDelegationCommunicationHab } from "../../app/identity/delegating.js";
|
|
3
4
|
import { endpointRoleAccepted, groupSigningMembers, isLocalGroupHab, localGroupMember, proposeGroupEndpointRole, } from "../../app/identity/endpoint-roleing.js";
|
|
4
5
|
import { uniqueMembers } from "../../app/multisig/group-members.js";
|
|
@@ -7,12 +8,24 @@ import { approvePendingMultisigProposal, commitAcceptedGroupMembers, eventAccept
|
|
|
7
8
|
import { runAgentRuntime } from "../../app/runtime/agent-runtime.js";
|
|
8
9
|
import { Receiptor, WitnessReceiptor } from "../../app/witness/receipting.js";
|
|
9
10
|
import { ValidationError } from "../../core/errors.js";
|
|
11
|
+
import { isV2RegistryRoute } from "../../core/exchange/protocol-exchanging.js";
|
|
10
12
|
import { Roles } from "../../core/roles.js";
|
|
11
13
|
import { withAgentRuntime } from "../common/context.js";
|
|
12
14
|
import { loadOptionObject, loadRotateFileOptions, parseBooleanOption, parseCountOption, parseDataItems, parseFileData, parseKeriVersionOption, parseNumberOption, parseStringListOption, parseStringOption, parseThresholdOption, } from "../common/parsing.js";
|
|
13
15
|
import { waitForIssuedCredential, waitForTelPublication } from "../common/tel-completion.js";
|
|
14
16
|
import { resolveWitnessAuths } from "../common/witness-auth.js";
|
|
15
17
|
const MULTISIG_TOPIC = "multisig";
|
|
18
|
+
/**
|
|
19
|
+
* Re-seal held registry roots to members an accepted group rotation added or
|
|
20
|
+
* rekeyed, as KERIpy `kli multisig rotate|join`. Runs while the command's
|
|
21
|
+
* runtime worker delivers; every outcome is returned, none fails the rotation.
|
|
22
|
+
*/
|
|
23
|
+
function* resealAfterRotation(hby, runtime, group, rotation) {
|
|
24
|
+
const ghab = hby.habs.get(group), root = runtime.registryRoot;
|
|
25
|
+
if (!ghab || !root)
|
|
26
|
+
return [];
|
|
27
|
+
return yield* resealRegistryRoots(root, runtime.postman, runtime.clock, ghab, rotation);
|
|
28
|
+
}
|
|
16
29
|
function requireText(value, label) {
|
|
17
30
|
if (!value) {
|
|
18
31
|
throw new ValidationError(`${label} is required and cannot be empty`);
|
|
@@ -132,6 +145,9 @@ export function* multisigJoinCommand(args) {
|
|
|
132
145
|
if (local.route === MULTISIG_ICP_ROUTE || local.route === MULTISIG_ROT_ROUTE) {
|
|
133
146
|
yield* completeDelegationIfNeeded(hby, runtime, local.group, commandArgs.proxy);
|
|
134
147
|
}
|
|
148
|
+
if (local.route === MULTISIG_ROT_ROUTE) {
|
|
149
|
+
return { ...local, rootCopies: yield* resealAfterRotation(hby, runtime, local.group, local.embedded) };
|
|
150
|
+
}
|
|
135
151
|
}
|
|
136
152
|
return local;
|
|
137
153
|
}
|
|
@@ -149,12 +165,19 @@ export function* multisigJoinCommand(args) {
|
|
|
149
165
|
tel.publicationComplete = publication.complete(tel.pre, tel.sn);
|
|
150
166
|
return result;
|
|
151
167
|
}
|
|
168
|
+
if (isV2RegistryRoute(result.route)) {
|
|
169
|
+
result.accepted = yield* settleRegistryApproval(hby, runtime, result, commandArgs, approval.deadline);
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
152
172
|
if (result.accepted) {
|
|
153
173
|
yield* receiptAcceptedEvent(hby, result.group, commandArgs, runtime);
|
|
154
174
|
if (result.route === MULTISIG_ICP_ROUTE
|
|
155
175
|
|| result.route === MULTISIG_ROT_ROUTE) {
|
|
156
176
|
yield* completeDelegationIfNeeded(hby, runtime, result.group, commandArgs.proxy);
|
|
157
177
|
}
|
|
178
|
+
if (result.route === MULTISIG_ROT_ROUTE) {
|
|
179
|
+
return { ...result, rootCopies: yield* resealAfterRotation(hby, runtime, result.group, result.embedded) };
|
|
180
|
+
}
|
|
158
181
|
}
|
|
159
182
|
return result;
|
|
160
183
|
});
|
|
@@ -253,11 +276,13 @@ export function* multisigRotateCommand(args) {
|
|
|
253
276
|
auto: true,
|
|
254
277
|
}));
|
|
255
278
|
let delegationPhase = null;
|
|
279
|
+
let rootCopies = [];
|
|
256
280
|
if (accepted) {
|
|
257
281
|
// The proposer's own acceptance must commit the rotated membership as a joiner's does.
|
|
258
282
|
commitAcceptedGroupMembers(hby, rotated.serder, smids, rmids);
|
|
259
283
|
yield* receiptAcceptedEvent(hby, rotated.hab.pre, commandArgs, runtime);
|
|
260
284
|
delegationPhase = yield* completeDelegationIfNeeded(hby, runtime, rotated.hab.pre, commandArgs.proxy);
|
|
285
|
+
rootCopies = yield* resealAfterRotation(hby, runtime, rotated.hab.pre, rotated.serder.said);
|
|
261
286
|
}
|
|
262
287
|
return {
|
|
263
288
|
route: MULTISIG_ROT_ROUTE,
|
|
@@ -267,6 +292,7 @@ export function* multisigRotateCommand(args) {
|
|
|
267
292
|
deliveries,
|
|
268
293
|
state: hby.db.getState(rotated.hab.pre),
|
|
269
294
|
delegationPhase: delegationPhase,
|
|
295
|
+
rootCopies,
|
|
270
296
|
};
|
|
271
297
|
});
|
|
272
298
|
}
|
|
@@ -432,8 +458,9 @@ function approvePrompt(args, context) {
|
|
|
432
458
|
* @param pre Accepted group event subject.
|
|
433
459
|
* @param args Witness authentication and HTTP endpoint mode choices.
|
|
434
460
|
* @param runtime Borrowed composed runtime; caller owns its worker and store lifetime.
|
|
461
|
+
* @param sn Accepted event ordinal to receipt; defaults to the current event.
|
|
435
462
|
*/
|
|
436
|
-
function* receiptAcceptedEvent(hby, pre, args, runtime) {
|
|
463
|
+
function* receiptAcceptedEvent(hby, pre, args, runtime, sn) {
|
|
437
464
|
const kever = hby.db.getKever(pre);
|
|
438
465
|
if (!kever || kever.wits.length === 0) {
|
|
439
466
|
return;
|
|
@@ -444,11 +471,42 @@ function* receiptAcceptedEvent(hby, pre, args, runtime) {
|
|
|
444
471
|
});
|
|
445
472
|
if (args.endpoint) {
|
|
446
473
|
const receiptor = new Receiptor(hby, runtime.protocol, runtime.http, runtime.clock);
|
|
447
|
-
yield* receiptor.receipt(pre, { sn: kever.sn, auths });
|
|
474
|
+
yield* receiptor.receipt(pre, { sn: sn ?? kever.sn, auths });
|
|
448
475
|
}
|
|
449
476
|
else {
|
|
450
477
|
const witDoer = new WitnessReceiptor(hby, runtime.protocol, runtime.http, runtime.clock);
|
|
451
|
-
yield* witDoer.submit(pre, { sn: kever.sn, auths });
|
|
478
|
+
yield* witDoer.submit(pre, { sn: sn ?? kever.sn, auths });
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Settle one approved v2 RIP/BUP as KERIpy's join Counselor does: wait for the group's KEL acceptance of
|
|
483
|
+
* the exact anchor, converge that anchor's witness receipts, and let the anchor escrow accept the TEL event.
|
|
484
|
+
* The TEL event needs a fully witnessed anchor, so receipting only after TEL acceptance would never accept it.
|
|
485
|
+
*
|
|
486
|
+
* @returns Whether the approved TEL event is accepted before the approval deadline.
|
|
487
|
+
*/
|
|
488
|
+
function* settleRegistryApproval(hby, runtime, result, args, deadline) {
|
|
489
|
+
const store = runtime.acdc?.store, tel = store?.event(result.embedded);
|
|
490
|
+
const anc = hby.db.exns.get([result.said])?.sad?.a?.anc;
|
|
491
|
+
if (!store || !tel || typeof tel.sad?.n !== "string" || typeof anc !== "string")
|
|
492
|
+
return result.accepted;
|
|
493
|
+
const regid = tel.ilk === "rip" ? tel.said : tel.regid, sn = Number(BigInt(`0x${tel.sad.n}`));
|
|
494
|
+
let receipted = false;
|
|
495
|
+
while (true) {
|
|
496
|
+
if (store.seqEvent(regid, sn)?.said === tel.said)
|
|
497
|
+
return true;
|
|
498
|
+
const anchor = hby.db.getEvtSerder(result.group, anc);
|
|
499
|
+
if (!receipted && anchor && hby.db.kels.getLast(result.group, anchor.sn) === anc) {
|
|
500
|
+
if (!hby.db.fullyWitnessed(anchor))
|
|
501
|
+
yield* receiptAcceptedEvent(hby, result.group, args, runtime, anchor.sn);
|
|
502
|
+
receipted = true;
|
|
503
|
+
}
|
|
504
|
+
yield* runtime.protocol.processEscrowsOnce();
|
|
505
|
+
if (store.seqEvent(regid, sn)?.said === tel.said)
|
|
506
|
+
return true;
|
|
507
|
+
if (Date.now() >= deadline)
|
|
508
|
+
return false;
|
|
509
|
+
yield* sleep(Math.min(250, deadline - Date.now()));
|
|
452
510
|
}
|
|
453
511
|
}
|
|
454
512
|
/** Approval waits allow fractional seconds and zero, but never coerce absence or overflow a deadline. */
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as dntShim from "../../_dnt.shims.js";
|
|
2
2
|
import { annotate } from "cesr-ts";
|
|
3
3
|
import { abortable } from "../../app/runtime/abortable.js";
|
|
4
|
-
import { collectBytes,
|
|
4
|
+
import { collectBytes, streamBytes } from "../../app/transport/byte-source.js";
|
|
5
|
+
import { fileBytes } from "../../app/transport/file-bytes.js";
|
|
5
6
|
import { parseBooleanOption, parseStringOption } from "../common/parsing.js";
|
|
6
7
|
import { writeStdout } from "../output.js";
|
|
7
8
|
import { colorizeAnnotatedOutput } from "./annotate-color.js";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as dntShim from "../../_dnt.shims.js";
|
|
2
2
|
import { benchmarkParser, } from "cesr-ts";
|
|
3
3
|
import { abortable } from "../../app/runtime/abortable.js";
|
|
4
|
-
import { collectBytes,
|
|
4
|
+
import { collectBytes, streamBytes } from "../../app/transport/byte-source.js";
|
|
5
|
+
import { fileBytes } from "../../app/transport/file-bytes.js";
|
|
5
6
|
import { ValidationError } from "../../core/errors.js";
|
|
6
7
|
import { parseBooleanOption, parseCountOption, parseStringOption } from "../common/parsing.js";
|
|
7
8
|
import { writeStdout } from "../output.js";
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { displayStr } from "../../core/bytes.js";
|
|
2
2
|
import { DatabaseOperationError, ValidationError } from "../../core/errors.js";
|
|
3
3
|
import { RawRecord } from "../../core/records.js";
|
|
4
|
-
import { createBaser } from "../../db/
|
|
5
|
-
import { createKeeper } from "../../db/keeping.js";
|
|
6
|
-
import { createMailboxer } from "../../db/mailbox/mailboxing.js";
|
|
7
|
-
import { createNoter } from "../../db/noting.js";
|
|
4
|
+
import { createBaser, createKeeper, createMailboxer, createNoter } from "../../db/lmdb-stores.js";
|
|
8
5
|
import { parseBooleanOption, parseIntegerOption, parseStringOption } from "../common/parsing.js";
|
|
9
6
|
const DOMAIN_FACTORIES = {
|
|
10
7
|
baser: {
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/** Unsigned bytewise order, shorter first on a shared prefix, as LMDB orders keys. */
|
|
2
|
+
export function compareBytes(left, right) {
|
|
3
|
+
const shared = Math.min(left.length, right.length);
|
|
4
|
+
for (let i = 0; i < shared; i++) {
|
|
5
|
+
if (left[i] !== right[i])
|
|
6
|
+
return left[i] - right[i];
|
|
7
|
+
}
|
|
8
|
+
return left.length - right.length;
|
|
9
|
+
}
|
|
1
10
|
/**
|
|
2
11
|
* Check if keyBytes starts with prefixBytes
|
|
3
12
|
*/
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { dgKey } from "../../db/core/keys.js";
|
|
2
|
+
import { ValidationError } from "../errors.js";
|
|
3
|
+
/** Whether one accepted delegator event carries the exact `{i,s,d}` seal of a delegated inception. */
|
|
4
|
+
function approves(event, dip) {
|
|
5
|
+
return event.eventSeals.some((seal) => seal.i.qb64 === dip.pre && seal.s.numh === dip.snh && seal.d.qb64 === dip.said);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Find the delegator's accepted approval of `dip`.
|
|
9
|
+
*
|
|
10
|
+
* The aess source couple is a fast path only when it names a first-seen event
|
|
11
|
+
* that actually carries the dip seal; protected intake can retain an unverified
|
|
12
|
+
* hint, which neither grants authority nor vetoes a later genuine approval.
|
|
13
|
+
* Otherwise any first-seen delegator event carrying the seal is accepted,
|
|
14
|
+
* including one superseded since, so cached and uncached validators agree.
|
|
15
|
+
*/
|
|
16
|
+
function acceptedApproval(db, delegator, dip) {
|
|
17
|
+
const source = db.aess.get(dgKey(dip.pre, dip.said));
|
|
18
|
+
if (source) {
|
|
19
|
+
const digest = source[1].qb64;
|
|
20
|
+
if (db.fons.get(dgKey(delegator, digest))) {
|
|
21
|
+
const approval = db.getEvtSerder(delegator, digest);
|
|
22
|
+
if (!approval)
|
|
23
|
+
throw new ValidationError(`Missing first-seen delegation event ${delegator}:${digest}.`);
|
|
24
|
+
if (approves(approval, dip))
|
|
25
|
+
return approval;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
for (const [, , said] of db.fels.getAllItemIter(delegator)) {
|
|
29
|
+
if (!db.fons.get(dgKey(delegator, said)))
|
|
30
|
+
continue;
|
|
31
|
+
const event = db.getEvtSerder(delegator, said);
|
|
32
|
+
if (event && approves(event, dip))
|
|
33
|
+
return event;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolve whether `pre` is an anchored delegated descendant of `ancestor`, at any depth.
|
|
39
|
+
*
|
|
40
|
+
* Every hop requires the delegate's fixed dip, the delegator's inception
|
|
41
|
+
* permission (DND is checked before the anchor) and an accepted delegator
|
|
42
|
+
* approval of that dip. Identity (`pre === ancestor`) is not delegation; the
|
|
43
|
+
* DI2I/DI1I callers own that widening.
|
|
44
|
+
*
|
|
45
|
+
* Security rationale, preserved from KERIpy's `relating.delegationRefusal`:
|
|
46
|
+
* - The delegate's own `di` (Kever.delpre) is a self-assertion. Local, member
|
|
47
|
+
* or witness acceptance can admit a dip whose delegator never anchored it, so
|
|
48
|
+
* only the delegator's anchored approval seal records actual authority.
|
|
49
|
+
* - DND is re-read from the delegator's accepted inception, not mutable state,
|
|
50
|
+
* because that same exemption can admit dips a disinterested validator would
|
|
51
|
+
* refuse; identical bytes must not get opposite verdicts by host topology.
|
|
52
|
+
* - Only the dip anchor matters. A delegation is settled at inception; later
|
|
53
|
+
* delegate rotations, delegator rotations, witness changes and retirement do
|
|
54
|
+
* not renew or revoke it.
|
|
55
|
+
* - No depth bound: a delegated prefix digests its own dip, so a cycle implies
|
|
56
|
+
* a hash cycle. The visited set only terminates corrupt local state.
|
|
57
|
+
*
|
|
58
|
+
* Unlike KERIpy, lookup never repairs aess; accepted KEL intake owns those writes.
|
|
59
|
+
* An aess couple naming a first-seen event that is absent from `evts` is
|
|
60
|
+
* corrupt durable state and throws.
|
|
61
|
+
*/
|
|
62
|
+
export function delegationAncestry(db, pre, ancestor) {
|
|
63
|
+
const seen = new Set();
|
|
64
|
+
while (!seen.has(pre)) {
|
|
65
|
+
seen.add(pre);
|
|
66
|
+
const kever = db.getKever(pre);
|
|
67
|
+
if (!kever)
|
|
68
|
+
return { kind: "pending", reason: `Missing delegate KEL ${pre}.` };
|
|
69
|
+
const parent = kever.delpre;
|
|
70
|
+
if (!parent)
|
|
71
|
+
return { kind: "refused", reason: `Delegation chain ends at ${pre}.` };
|
|
72
|
+
if (!db.getKever(parent))
|
|
73
|
+
return { kind: "pending", reason: `Missing delegator KEL ${parent}.` };
|
|
74
|
+
// Configuration is fixed at inception, including after delegator rotations.
|
|
75
|
+
const inceptionSaid = db.kels.getLast(parent, 0);
|
|
76
|
+
const inception = inceptionSaid ? db.getEvtSerder(parent, inceptionSaid) : null;
|
|
77
|
+
if (!inception)
|
|
78
|
+
return { kind: "pending", reason: `Missing delegator inception ${parent}.` };
|
|
79
|
+
if (inception.traits.includes("DND"))
|
|
80
|
+
return { kind: "refused", reason: `Delegator ${parent} carries DND.` };
|
|
81
|
+
const dip = db.getEvtSerder(pre, pre);
|
|
82
|
+
if (!dip)
|
|
83
|
+
return { kind: "pending", reason: `Missing delegated inception ${pre}.` };
|
|
84
|
+
if (!acceptedApproval(db, parent, dip)) {
|
|
85
|
+
return { kind: "pending", reason: `Missing accepted delegation approval for ${pre} from ${parent}.` };
|
|
86
|
+
}
|
|
87
|
+
if (parent === ancestor)
|
|
88
|
+
return { kind: "valid" };
|
|
89
|
+
pre = parent;
|
|
90
|
+
}
|
|
91
|
+
return { kind: "refused", reason: `Delegation chain cycles at ${pre}.` };
|
|
92
|
+
}
|
|
@@ -126,7 +126,6 @@ export class Kevery {
|
|
|
126
126
|
return this.settleEventDecision(envelope);
|
|
127
127
|
}
|
|
128
128
|
settleEventDecision(input, escrow) {
|
|
129
|
-
const env = this.db.env;
|
|
130
129
|
if (this.db.inWriteTransaction) {
|
|
131
130
|
throw new Error("Kevery must own the KEL transaction; process events outside caller-owned writers");
|
|
132
131
|
}
|
|
@@ -151,7 +150,7 @@ export class Kevery {
|
|
|
151
150
|
this.removeEscrow(escrow.kind, escrow.pre, escrow.on, escrow.said);
|
|
152
151
|
return decision;
|
|
153
152
|
};
|
|
154
|
-
const decision =
|
|
153
|
+
const decision = this.db.transaction(write);
|
|
155
154
|
this.publishEventState(metadata?.accepted);
|
|
156
155
|
if (metadata?.cues.length)
|
|
157
156
|
this.cues.extend(metadata.cues);
|
|
@@ -551,21 +551,23 @@ export class Kever {
|
|
|
551
551
|
return indices;
|
|
552
552
|
}
|
|
553
553
|
/**
|
|
554
|
-
* Return indices
|
|
554
|
+
* Return indices of keys contributed by this group's local members.
|
|
555
555
|
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
*
|
|
556
|
+
* KERIpy strips its one local member (`habord.mid`). A keri-ts Habery may hold
|
|
557
|
+
* several members of one group, so every locally controlled signing member
|
|
558
|
+
* counts. The group's own prefix is local too and must not: its keys are all
|
|
559
|
+
* of `verfers`.
|
|
559
560
|
*/
|
|
560
561
|
locallyContributedIndices(verfers) {
|
|
562
|
+
const record = this.db.getHab(this.pre);
|
|
561
563
|
const localKeys = new Set();
|
|
562
|
-
for (const
|
|
563
|
-
|
|
564
|
-
if (!kever) {
|
|
564
|
+
for (const mid of new Set([record?.mid, ...(record?.smids ?? [])])) {
|
|
565
|
+
if (!mid || !this.locallyOwned(mid)) {
|
|
565
566
|
continue;
|
|
566
567
|
}
|
|
567
|
-
|
|
568
|
-
|
|
568
|
+
const key = this.db.getKever(mid)?.verfers[0]?.qb64;
|
|
569
|
+
if (key) {
|
|
570
|
+
localKeys.add(key);
|
|
569
571
|
}
|
|
570
572
|
}
|
|
571
573
|
const indices = [];
|
|
@@ -298,11 +298,10 @@ export class KramPolicy {
|
|
|
298
298
|
}
|
|
299
299
|
/** Publish policy rows and their restart-safe transition metadata atomically. */
|
|
300
300
|
commit(mutate) {
|
|
301
|
-
|
|
302
|
-
if (!env)
|
|
301
|
+
if (!this.db.opened)
|
|
303
302
|
throw new Error("KRAM policy database is closed");
|
|
304
303
|
const next = JSON.stringify(this.state);
|
|
305
|
-
|
|
304
|
+
this.db.transaction(() => {
|
|
306
305
|
if (this.db.hbys.get(policyKey) !== this.storedState)
|
|
307
306
|
throw new Error("KRAM policy changed during transition");
|
|
308
307
|
mutate();
|
|
@@ -19,7 +19,7 @@ export class KramPruner {
|
|
|
19
19
|
writable: true,
|
|
20
20
|
value: policy
|
|
21
21
|
});
|
|
22
|
-
Object.defineProperty(this, "
|
|
22
|
+
Object.defineProperty(this, "bound", {
|
|
23
23
|
enumerable: true,
|
|
24
24
|
configurable: true,
|
|
25
25
|
writable: true,
|
|
@@ -46,24 +46,18 @@ export class KramPruner {
|
|
|
46
46
|
if (policy.db !== db)
|
|
47
47
|
throw new Error("KRAM pruning policy must use its backing store");
|
|
48
48
|
}
|
|
49
|
-
/** Use committed environment state, never assume transaction IDs increment by one. */
|
|
50
|
-
version() {
|
|
51
|
-
const version = this.db.env.getStats().lastTxnId;
|
|
52
|
-
if (!Number.isSafeInteger(version) || version < 0)
|
|
53
|
-
throw new Error("Invalid KRAM pruning transaction ID");
|
|
54
|
-
return version;
|
|
55
|
-
}
|
|
56
49
|
/** Capture a finite horizon and release each tail/next iterator before returning. */
|
|
57
50
|
next(family, scan) {
|
|
58
51
|
const table = [this.db.msgc, this.db.tmsc, this.db.xdt][family];
|
|
59
52
|
if (!scan.initialized) {
|
|
60
|
-
for (const key of table.sdb
|
|
53
|
+
for (const key of this.db.scanKeys(table.sdb, { reverse: true, limit: 1 }))
|
|
61
54
|
scan.end = this.after(key);
|
|
62
55
|
scan.initialized = true;
|
|
63
56
|
}
|
|
64
57
|
if (scan.end) {
|
|
65
|
-
for (const key of table.sdb
|
|
58
|
+
for (const key of this.db.scanKeys(table.sdb, { start: scan.start, end: scan.end, limit: 1 })) {
|
|
66
59
|
return key.slice();
|
|
60
|
+
}
|
|
67
61
|
}
|
|
68
62
|
}
|
|
69
63
|
/** Qualified cache components contain no NUL, so this seeks strictly after a complete key. */
|
|
@@ -102,17 +96,16 @@ export class KramPruner {
|
|
|
102
96
|
if (!Number.isSafeInteger(maxRows) || maxRows < 1)
|
|
103
97
|
throw new RangeError("Invalid KRAM pruning batch");
|
|
104
98
|
const result = { kind: "pruned", visited: 0, removed: 0, openers: 0, passComplete: false };
|
|
105
|
-
|
|
106
|
-
if (!env)
|
|
99
|
+
if (!this.db.opened)
|
|
107
100
|
throw new Error("KRAM pruning database is closed");
|
|
108
|
-
if (this.
|
|
109
|
-
this.
|
|
101
|
+
if (this.bound !== this.db.msgc.sdb) {
|
|
102
|
+
this.bound = this.db.msgc.sdb;
|
|
110
103
|
this.phase = 0;
|
|
111
104
|
this.scans = [{}, {}, {}];
|
|
112
105
|
this.orphan = undefined;
|
|
113
106
|
}
|
|
114
107
|
this.policy.reconcile();
|
|
115
|
-
|
|
108
|
+
this.db.refreshRead();
|
|
116
109
|
while (result.visited < maxRows) {
|
|
117
110
|
if (this.phase < 2) {
|
|
118
111
|
const scan = this.scans[this.phase], physical = this.next(this.phase, scan);
|
|
@@ -121,7 +114,7 @@ export class KramPruner {
|
|
|
121
114
|
continue;
|
|
122
115
|
}
|
|
123
116
|
const keys = this.keys(physical, this.phase + 2), table = this.phase ? this.db.tmsc : this.db.msgc;
|
|
124
|
-
|
|
117
|
+
this.db.transaction(() => {
|
|
125
118
|
const record = table.get(keys);
|
|
126
119
|
if (!record || !this.expired(record, when))
|
|
127
120
|
return;
|
|
@@ -144,17 +137,17 @@ export class KramPruner {
|
|
|
144
137
|
}
|
|
145
138
|
const [xid] = this.keys(physical, 1);
|
|
146
139
|
this.db.xdt.get(xid); // Deserialization failures remain corruption, not an absent opener.
|
|
147
|
-
this.orphan = { xid, physical, scan: {}, version: this.
|
|
140
|
+
this.orphan = { xid, physical, scan: {}, version: this.db.writeVersion };
|
|
148
141
|
result.visited++;
|
|
149
142
|
continue;
|
|
150
143
|
}
|
|
151
|
-
const candidate = this.orphan, version = this.
|
|
144
|
+
const candidate = this.orphan, version = this.db.writeVersion;
|
|
152
145
|
if (candidate.version !== version) {
|
|
153
146
|
candidate.scan = {};
|
|
154
147
|
candidate.version = version;
|
|
155
148
|
}
|
|
156
149
|
// Capture committed version before opening a fresh read snapshot, including other-process writes.
|
|
157
|
-
|
|
150
|
+
this.db.refreshRead();
|
|
158
151
|
const physical = this.next(1, candidate.scan);
|
|
159
152
|
if (physical) {
|
|
160
153
|
const keys = this.keys(physical, 3);
|
|
@@ -165,8 +158,8 @@ export class KramPruner {
|
|
|
165
158
|
}
|
|
166
159
|
else {
|
|
167
160
|
result.visited++;
|
|
168
|
-
const removed =
|
|
169
|
-
if (candidate.version !== this.
|
|
161
|
+
const removed = this.db.transaction(() => {
|
|
162
|
+
if (candidate.version !== this.db.writeVersion)
|
|
170
163
|
return false;
|
|
171
164
|
if (this.db.xdt.rem(candidate.xid))
|
|
172
165
|
result.openers++;
|
|
@@ -174,7 +167,7 @@ export class KramPruner {
|
|
|
174
167
|
});
|
|
175
168
|
if (!removed) {
|
|
176
169
|
candidate.scan = {};
|
|
177
|
-
candidate.version = this.
|
|
170
|
+
candidate.version = this.db.writeVersion;
|
|
178
171
|
continue;
|
|
179
172
|
}
|
|
180
173
|
}
|
|
@@ -98,9 +98,9 @@ function candidate(db, policy, incoming, receiverTime) {
|
|
|
98
98
|
* borrowed from the current input and are never read or disposed by KRAM.
|
|
99
99
|
*/
|
|
100
100
|
export function stageKram(db, policy, incoming, receiverTime) {
|
|
101
|
-
if (!db.
|
|
101
|
+
if (!db.opened)
|
|
102
102
|
throw new Error("KRAM staging database is closed");
|
|
103
|
-
return db.
|
|
103
|
+
return db.transaction(() => {
|
|
104
104
|
const fresh = candidate(db, policy, incoming, receiverTime);
|
|
105
105
|
if (fresh.kind === "rotated") {
|
|
106
106
|
removeKramFactors(db, fresh.key);
|
|
@@ -820,7 +820,7 @@ export class BasicReplyRouteHandler {
|
|
|
820
820
|
throw new Error("Endpoint handler must own the reply transaction; process replies outside caller-owned writers");
|
|
821
821
|
}
|
|
822
822
|
let queryCues = [];
|
|
823
|
-
const decision = this.rvy.db.
|
|
823
|
+
const decision = this.rvy.db.transaction(() => {
|
|
824
824
|
let osaider = this.rvy.db.eans.get(keys);
|
|
825
825
|
if (osaider?.qb64 === args.diger.qb64)
|
|
826
826
|
osaider = null;
|
|
@@ -881,7 +881,7 @@ export class BasicReplyRouteHandler {
|
|
|
881
881
|
throw new Error("Endpoint handler must own the reply transaction; process replies outside caller-owned writers");
|
|
882
882
|
}
|
|
883
883
|
let queryCues = [];
|
|
884
|
-
const decision = this.rvy.db.
|
|
884
|
+
const decision = this.rvy.db.transaction(() => {
|
|
885
885
|
let osaider = this.rvy.db.lans.get(keys);
|
|
886
886
|
if (osaider?.qb64 === args.diger.qb64)
|
|
887
887
|
osaider = null;
|