dero-mcp-server 0.1.2 → 0.4.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/POSITIONING.md +94 -0
- package/README.md +132 -31
- package/SKILL.md +264 -0
- package/data/docs-index.json +276 -264
- package/dist/bn254.d.ts +74 -0
- package/dist/bn254.d.ts.map +1 -0
- package/dist/bn254.js +205 -0
- package/dist/bn254.js.map +1 -0
- package/dist/citations.d.ts +140 -0
- package/dist/citations.d.ts.map +1 -0
- package/dist/citations.js +322 -0
- package/dist/citations.js.map +1 -0
- package/dist/composites/_shared.d.ts +119 -0
- package/dist/composites/_shared.d.ts.map +1 -0
- package/dist/composites/_shared.js +152 -0
- package/dist/composites/_shared.js.map +1 -0
- package/dist/composites/audit-chain-artifact-claim.d.ts +128 -0
- package/dist/composites/audit-chain-artifact-claim.d.ts.map +1 -0
- package/dist/composites/audit-chain-artifact-claim.js +305 -0
- package/dist/composites/audit-chain-artifact-claim.js.map +1 -0
- package/dist/composites/diagnose-chain-health.d.ts +64 -0
- package/dist/composites/diagnose-chain-health.d.ts.map +1 -0
- package/dist/composites/diagnose-chain-health.js +144 -0
- package/dist/composites/diagnose-chain-health.js.map +1 -0
- package/dist/composites/estimate-deploy-cost.d.ts +83 -0
- package/dist/composites/estimate-deploy-cost.d.ts.map +1 -0
- package/dist/composites/estimate-deploy-cost.js +116 -0
- package/dist/composites/estimate-deploy-cost.js.map +1 -0
- package/dist/composites/explain-smart-contract.d.ts +64 -0
- package/dist/composites/explain-smart-contract.d.ts.map +1 -0
- package/dist/composites/explain-smart-contract.js +149 -0
- package/dist/composites/explain-smart-contract.js.map +1 -0
- package/dist/composites/forge-demo-proof.d.ts +81 -0
- package/dist/composites/forge-demo-proof.d.ts.map +1 -0
- package/dist/composites/forge-demo-proof.js +204 -0
- package/dist/composites/forge-demo-proof.js.map +1 -0
- package/dist/composites/recommend-docs-path.d.ts +97 -0
- package/dist/composites/recommend-docs-path.d.ts.map +1 -0
- package/dist/composites/recommend-docs-path.js +149 -0
- package/dist/composites/recommend-docs-path.js.map +1 -0
- package/dist/composites/trace-transaction-with-context.d.ts +107 -0
- package/dist/composites/trace-transaction-with-context.d.ts.map +1 -0
- package/dist/composites/trace-transaction-with-context.js +217 -0
- package/dist/composites/trace-transaction-with-context.js.map +1 -0
- package/dist/daemon-base.d.ts +28 -0
- package/dist/daemon-base.d.ts.map +1 -0
- package/dist/daemon-base.js +62 -0
- package/dist/daemon-base.js.map +1 -0
- package/dist/dero-curve.d.ts +79 -0
- package/dist/dero-curve.d.ts.map +1 -0
- package/dist/dero-curve.js +79 -0
- package/dist/dero-curve.js.map +1 -0
- package/dist/docs-parse.d.ts.map +1 -1
- package/dist/docs-parse.js +18 -2
- package/dist/docs-parse.js.map +1 -1
- package/dist/http-server.d.ts +37 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +132 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.js +18 -11
- package/dist/index.js.map +1 -1
- package/dist/proof-decode.d.ts +125 -0
- package/dist/proof-decode.d.ts.map +1 -0
- package/dist/proof-decode.js +619 -0
- package/dist/proof-decode.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +414 -114
- package/dist/server.js.map +1 -1
- package/dist/tool-descriptions.d.ts +53 -0
- package/dist/tool-descriptions.d.ts.map +1 -0
- package/dist/tool-descriptions.js +285 -0
- package/dist/tool-descriptions.js.map +1 -0
- package/dist/tx-parse.d.ts +63 -0
- package/dist/tx-parse.d.ts.map +1 -0
- package/dist/tx-parse.js +183 -0
- package/dist/tx-parse.js.map +1 -0
- package/package.json +27 -2
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `audit_chain_artifact_claim` — composite #6.
|
|
3
|
+
*
|
|
4
|
+
* Given a chain artifact (block topoheight, block hash, TX hash, and/or
|
|
5
|
+
* proof string), return a single verdict-shaped response that combines:
|
|
6
|
+
* - the canonical chain facts (block reward, txcount, TX acceptance, …)
|
|
7
|
+
* - a check against the flagged-artifact registry (false-claim citations)
|
|
8
|
+
* - a narrative the agent can relay verbatim
|
|
9
|
+
* - curated `related_docs` (rebuttal pages when flagged, generic when clean)
|
|
10
|
+
*
|
|
11
|
+
* Use case: a user asks an AI "what's going on with DERO block 1,081,893?"
|
|
12
|
+
* or pastes a `deroproof…` string. Instead of returning raw RPC numbers
|
|
13
|
+
* with no framing — which can read as "agreement with whatever framing the
|
|
14
|
+
* user implied" under hostile readership — this composite returns a
|
|
15
|
+
* factual verdict + the rebuttal context.
|
|
16
|
+
*
|
|
17
|
+
* Pairs with the silent enrichment in `citations.ts`: that fires when an
|
|
18
|
+
* agent queries primitives directly; this composite is for when an agent
|
|
19
|
+
* (or user) explicitly wants to audit an artifact end-to-end.
|
|
20
|
+
*
|
|
21
|
+
* Failure model:
|
|
22
|
+
* - Validates that at least one artifact field is provided. Throws
|
|
23
|
+
* `INVALID_INPUT` otherwise — handled by `withStructuredErrors`.
|
|
24
|
+
* - Daemon calls are non-required (kept independent so the verdict still
|
|
25
|
+
* lands even if the daemon is offline). Their failures degrade
|
|
26
|
+
* `chain_facts` to null and surface in `_diagnostics`.
|
|
27
|
+
* - Proof-string decoding errors are caught and surfaced under
|
|
28
|
+
* `proof_decode.error` rather than throwing — the verdict still lands.
|
|
29
|
+
*/
|
|
30
|
+
import { z } from 'zod';
|
|
31
|
+
import { type DeroCitation } from '../citations.js';
|
|
32
|
+
import { interpretValueTransfer } from '../proof-decode.js';
|
|
33
|
+
import { type ForgeDemoProofResult } from './forge-demo-proof.js';
|
|
34
|
+
import { type DeroDaemonRpc } from './_shared.js';
|
|
35
|
+
export declare const auditChainArtifactClaimInputSchema: {
|
|
36
|
+
readonly topoheight: z.ZodOptional<z.ZodNumber>;
|
|
37
|
+
readonly block_hash: z.ZodOptional<z.ZodString>;
|
|
38
|
+
readonly tx_hash: z.ZodOptional<z.ZodString>;
|
|
39
|
+
readonly proof_string: z.ZodOptional<z.ZodString>;
|
|
40
|
+
readonly include_forge_demo: z.ZodOptional<z.ZodBoolean>;
|
|
41
|
+
};
|
|
42
|
+
export type AuditChainArtifactClaimInput = {
|
|
43
|
+
topoheight?: number;
|
|
44
|
+
block_hash?: string;
|
|
45
|
+
tx_hash?: string;
|
|
46
|
+
proof_string?: string;
|
|
47
|
+
include_forge_demo?: boolean;
|
|
48
|
+
};
|
|
49
|
+
type BlockHeaderResult = {
|
|
50
|
+
block_header?: {
|
|
51
|
+
topoheight?: number;
|
|
52
|
+
height?: number;
|
|
53
|
+
hash?: string;
|
|
54
|
+
timestamp?: number;
|
|
55
|
+
reward?: number;
|
|
56
|
+
txcount?: number;
|
|
57
|
+
};
|
|
58
|
+
status?: string;
|
|
59
|
+
};
|
|
60
|
+
type AuditVerdict = 'cited_in_false_claim' | 'clean';
|
|
61
|
+
type AuditChainFacts = {
|
|
62
|
+
block_header?: BlockHeaderResult['block_header'];
|
|
63
|
+
transaction_status?: {
|
|
64
|
+
accepted: boolean;
|
|
65
|
+
in_pool: boolean;
|
|
66
|
+
block_height: number | null;
|
|
67
|
+
valid_block: string | null;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
type AuditProofDecode = {
|
|
71
|
+
hrp?: string;
|
|
72
|
+
is_proof?: boolean;
|
|
73
|
+
value_transfer_uint64?: string;
|
|
74
|
+
value_interpretation?: ReturnType<typeof interpretValueTransfer>;
|
|
75
|
+
error?: string;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Slimmed-down embedded forge result. Strips the duplicate citations/context
|
|
79
|
+
* note (the audit response already carries those at the top level) and
|
|
80
|
+
* diagnostics. Keeps the math + the actual forged string + the receiver +
|
|
81
|
+
* the self-check — the pieces that make this useful for the agent.
|
|
82
|
+
*/
|
|
83
|
+
export type EmbeddedForgeDemo = {
|
|
84
|
+
skipped: false;
|
|
85
|
+
forged_proof_string: string;
|
|
86
|
+
target_amount: ForgeDemoProofResult['target_amount'];
|
|
87
|
+
ring_slot: number;
|
|
88
|
+
ring_size: number;
|
|
89
|
+
ring_receiver_address: string | null;
|
|
90
|
+
math: ForgeDemoProofResult['math'];
|
|
91
|
+
self_check: ForgeDemoProofResult['self_check'];
|
|
92
|
+
explorer_display_amount: string;
|
|
93
|
+
demo_amount_source: 'flagged_artifact' | 'proof_string_v' | 'default';
|
|
94
|
+
} | {
|
|
95
|
+
skipped: true;
|
|
96
|
+
reason: string;
|
|
97
|
+
};
|
|
98
|
+
export type AuditChainArtifactClaimResult = {
|
|
99
|
+
verdict: AuditVerdict;
|
|
100
|
+
inputs: AuditChainArtifactClaimInput;
|
|
101
|
+
matched_artifacts: Array<{
|
|
102
|
+
id: string;
|
|
103
|
+
matched_by: string[];
|
|
104
|
+
}>;
|
|
105
|
+
context_note: string | null;
|
|
106
|
+
chain_facts: AuditChainFacts | null;
|
|
107
|
+
proof_decode: AuditProofDecode | null;
|
|
108
|
+
forge_demo: EmbeddedForgeDemo | null;
|
|
109
|
+
narrative: string;
|
|
110
|
+
related_docs: DeroCitation[];
|
|
111
|
+
_diagnostics: {
|
|
112
|
+
step_latencies: Record<string, number>;
|
|
113
|
+
halted_at: string | null;
|
|
114
|
+
total_ms: number;
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Execute the audit. Composes (in this order):
|
|
119
|
+
* 1. Flagged-artifact match against the inputs.
|
|
120
|
+
* 2. Optional `DERO.GetBlockHeaderByTopoHeight` / `DERO.GetBlockHeaderByHash`.
|
|
121
|
+
* 3. Optional `DERO.GetTransaction` for accepted/pool status.
|
|
122
|
+
* 4. Optional proof-string decode.
|
|
123
|
+
* 5. Optional forge-demo (when `include_forge_demo: true` and tx_hash present).
|
|
124
|
+
* 6. Narrative + related_docs assembly.
|
|
125
|
+
*/
|
|
126
|
+
export declare function auditChainArtifactClaim(rpc: DeroDaemonRpc, input: AuditChainArtifactClaimInput): Promise<AuditChainArtifactClaimResult>;
|
|
127
|
+
export {};
|
|
128
|
+
//# sourceMappingURL=audit-chain-artifact-claim.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-chain-artifact-claim.d.ts","sourceRoot":"","sources":["../../src/composites/audit-chain-artifact-claim.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `audit_chain_artifact_claim` — composite #6.
|
|
3
|
+
*
|
|
4
|
+
* Given a chain artifact (block topoheight, block hash, TX hash, and/or
|
|
5
|
+
* proof string), return a single verdict-shaped response that combines:
|
|
6
|
+
* - the canonical chain facts (block reward, txcount, TX acceptance, …)
|
|
7
|
+
* - a check against the flagged-artifact registry (false-claim citations)
|
|
8
|
+
* - a narrative the agent can relay verbatim
|
|
9
|
+
* - curated `related_docs` (rebuttal pages when flagged, generic when clean)
|
|
10
|
+
*
|
|
11
|
+
* Use case: a user asks an AI "what's going on with DERO block 1,081,893?"
|
|
12
|
+
* or pastes a `deroproof…` string. Instead of returning raw RPC numbers
|
|
13
|
+
* with no framing — which can read as "agreement with whatever framing the
|
|
14
|
+
* user implied" under hostile readership — this composite returns a
|
|
15
|
+
* factual verdict + the rebuttal context.
|
|
16
|
+
*
|
|
17
|
+
* Pairs with the silent enrichment in `citations.ts`: that fires when an
|
|
18
|
+
* agent queries primitives directly; this composite is for when an agent
|
|
19
|
+
* (or user) explicitly wants to audit an artifact end-to-end.
|
|
20
|
+
*
|
|
21
|
+
* Failure model:
|
|
22
|
+
* - Validates that at least one artifact field is provided. Throws
|
|
23
|
+
* `INVALID_INPUT` otherwise — handled by `withStructuredErrors`.
|
|
24
|
+
* - Daemon calls are non-required (kept independent so the verdict still
|
|
25
|
+
* lands even if the daemon is offline). Their failures degrade
|
|
26
|
+
* `chain_facts` to null and surface in `_diagnostics`.
|
|
27
|
+
* - Proof-string decoding errors are caught and surfaced under
|
|
28
|
+
* `proof_decode.error` rather than throwing — the verdict still lands.
|
|
29
|
+
*/
|
|
30
|
+
import { z } from 'zod';
|
|
31
|
+
import { enrichWithFlaggedArtifacts, flaggedArtifactsForInput, relatedDocsFor, } from '../citations.js';
|
|
32
|
+
import { decodeDeroBech32, interpretValueTransfer } from '../proof-decode.js';
|
|
33
|
+
import { forgeDemoProof } from './forge-demo-proof.js';
|
|
34
|
+
import { runChain, stepLatencies, stepValue, } from './_shared.js';
|
|
35
|
+
export const auditChainArtifactClaimInputSchema = {
|
|
36
|
+
topoheight: z
|
|
37
|
+
.number()
|
|
38
|
+
.int()
|
|
39
|
+
.nonnegative()
|
|
40
|
+
.optional()
|
|
41
|
+
.describe('Topological height of a block to audit.'),
|
|
42
|
+
block_hash: z
|
|
43
|
+
.string()
|
|
44
|
+
.regex(/^[0-9a-fA-F]{64}$/, 'block_hash must be 64 hex characters')
|
|
45
|
+
.optional()
|
|
46
|
+
.describe('64-char hex block hash to audit.'),
|
|
47
|
+
tx_hash: z
|
|
48
|
+
.string()
|
|
49
|
+
.regex(/^[0-9a-fA-F]{64}$/, 'tx_hash must be 64 hex characters')
|
|
50
|
+
.optional()
|
|
51
|
+
.describe('64-char hex transaction hash to audit.'),
|
|
52
|
+
proof_string: z
|
|
53
|
+
.string()
|
|
54
|
+
.min(8)
|
|
55
|
+
.optional()
|
|
56
|
+
.describe('Optional `deroproof…` / DERO bech32 string to also decode and check.'),
|
|
57
|
+
include_forge_demo: z
|
|
58
|
+
.boolean()
|
|
59
|
+
.optional()
|
|
60
|
+
.describe('When true AND tx_hash is provided, also forge a fresh demo proof for the same TX (via dero_forge_demo_proof) and embed it under `forge_demo`. Closes the rebuttal loop in one tool call. Default false.'),
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Build the human-readable narrative. Kept tight; agents are expected to
|
|
64
|
+
* relay this verbatim to the user.
|
|
65
|
+
*/
|
|
66
|
+
function buildNarrative(verdict, inputs, matched, chainFacts, proofDecode, forgeDemo) {
|
|
67
|
+
const parts = [];
|
|
68
|
+
if (verdict === 'cited_in_false_claim') {
|
|
69
|
+
const ids = matched.map((a) => a.id).join(', ');
|
|
70
|
+
parts.push(`The provided artifact(s) match ${matched.length} flagged false-claim record(s): ${ids}.`);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
parts.push('No matches found in the flagged false-claim registry for the provided artifact(s).');
|
|
74
|
+
}
|
|
75
|
+
if (chainFacts?.block_header) {
|
|
76
|
+
const h = chainFacts.block_header;
|
|
77
|
+
const reward = typeof h.reward === 'number' ? (h.reward / 100_000).toFixed(3) : 'n/a';
|
|
78
|
+
parts.push(`Block topoheight=${h.topoheight ?? '?'} hash=${(h.hash ?? '').slice(0, 16)}… reward=${reward} DERO txcount=${h.txcount ?? '?'}.`);
|
|
79
|
+
}
|
|
80
|
+
if (chainFacts?.transaction_status) {
|
|
81
|
+
const t = chainFacts.transaction_status;
|
|
82
|
+
if (t.accepted) {
|
|
83
|
+
parts.push(`Transaction was accepted into block height=${t.block_height ?? '?'} — meaning all six sigma proofs and the range proof passed at every validating node.`);
|
|
84
|
+
}
|
|
85
|
+
else if (t.in_pool) {
|
|
86
|
+
parts.push('Transaction is currently in the mempool (unconfirmed).');
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
parts.push('Transaction was not found on this daemon (could be wrong network or non-existent).');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (proofDecode && !proofDecode.error) {
|
|
93
|
+
if (proofDecode.value_interpretation) {
|
|
94
|
+
const v = proofDecode.value_interpretation;
|
|
95
|
+
parts.push(`Proof string decoded successfully — embedded uint64=${v.uint64} (signed interpretation: ${v.dero} DERO${v.is_negative_wraparound ? '; this is a uint64 wraparound of a negative atomic value' : ''}).`);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
parts.push(`Bech32 string decoded successfully (hrp=${proofDecode.hrp}).`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (proofDecode?.error) {
|
|
102
|
+
parts.push(`Proof-string decode failed: ${proofDecode.error}`);
|
|
103
|
+
}
|
|
104
|
+
if (forgeDemo && !forgeDemo.skipped) {
|
|
105
|
+
parts.push(`For comparison, we forged a fresh proof for ring slot ${forgeDemo.ring_slot} targeting ${forgeDemo.target_amount.dero} DERO (display amount ${forgeDemo.explorer_display_amount}). It self-verifies under the same equation proof.Prove() uses — meaning an unpatched explorer would mark it Verified ✓ — yet nothing on-chain moved. The cited payload proof is the same kind of object.`);
|
|
106
|
+
}
|
|
107
|
+
if (verdict === 'cited_in_false_claim') {
|
|
108
|
+
parts.push('See related_docs for the technical rebuttal — the cited payload proof is a display object, not a consensus record.');
|
|
109
|
+
}
|
|
110
|
+
return parts.join(' ');
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Execute the audit. Composes (in this order):
|
|
114
|
+
* 1. Flagged-artifact match against the inputs.
|
|
115
|
+
* 2. Optional `DERO.GetBlockHeaderByTopoHeight` / `DERO.GetBlockHeaderByHash`.
|
|
116
|
+
* 3. Optional `DERO.GetTransaction` for accepted/pool status.
|
|
117
|
+
* 4. Optional proof-string decode.
|
|
118
|
+
* 5. Optional forge-demo (when `include_forge_demo: true` and tx_hash present).
|
|
119
|
+
* 6. Narrative + related_docs assembly.
|
|
120
|
+
*/
|
|
121
|
+
export async function auditChainArtifactClaim(rpc, input) {
|
|
122
|
+
if (input.topoheight === undefined &&
|
|
123
|
+
!input.block_hash &&
|
|
124
|
+
!input.tx_hash &&
|
|
125
|
+
!input.proof_string) {
|
|
126
|
+
throw new Error('INVALID_INPUT: provide at least one of topoheight, block_hash, tx_hash, or proof_string');
|
|
127
|
+
}
|
|
128
|
+
// ─── 1. Flagged-artifact match ────────────────────────────────────────────
|
|
129
|
+
const matched = flaggedArtifactsForInput({
|
|
130
|
+
topoheight: input.topoheight,
|
|
131
|
+
block_hash: input.block_hash,
|
|
132
|
+
tx_hash: input.tx_hash,
|
|
133
|
+
proof_string: input.proof_string,
|
|
134
|
+
});
|
|
135
|
+
// ─── 2-3. Chain primitives (only the ones the inputs cover) ───────────────
|
|
136
|
+
const steps = [];
|
|
137
|
+
if (input.topoheight !== undefined) {
|
|
138
|
+
const topo = input.topoheight;
|
|
139
|
+
steps.push({
|
|
140
|
+
name: 'block_header_by_topo',
|
|
141
|
+
fn: () => rpc('DERO.GetBlockHeaderByTopoHeight', { topoheight: topo }),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
else if (input.block_hash) {
|
|
145
|
+
const hash = input.block_hash;
|
|
146
|
+
steps.push({
|
|
147
|
+
name: 'block_header_by_hash',
|
|
148
|
+
fn: () => rpc('DERO.GetBlockHeaderByHash', { hash }),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
if (input.tx_hash) {
|
|
152
|
+
const tx = input.tx_hash;
|
|
153
|
+
steps.push({
|
|
154
|
+
name: 'get_transaction',
|
|
155
|
+
fn: () => rpc('DERO.GetTransaction', { txs_hashes: [tx] }),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
const chain = await runChain(steps);
|
|
159
|
+
// ─── 4. Proof-string decode ───────────────────────────────────────────────
|
|
160
|
+
let proofDecode = null;
|
|
161
|
+
if (input.proof_string) {
|
|
162
|
+
try {
|
|
163
|
+
const decoded = decodeDeroBech32(input.proof_string);
|
|
164
|
+
const valueInterp = decoded.value_transfer_uint64 !== undefined
|
|
165
|
+
? interpretValueTransfer(decoded.value_transfer_uint64)
|
|
166
|
+
: undefined;
|
|
167
|
+
proofDecode = {
|
|
168
|
+
hrp: decoded.hrp,
|
|
169
|
+
is_proof: decoded.is_proof,
|
|
170
|
+
...(decoded.value_transfer_uint64 !== undefined
|
|
171
|
+
? { value_transfer_uint64: decoded.value_transfer_uint64.toString() }
|
|
172
|
+
: {}),
|
|
173
|
+
...(valueInterp ? { value_interpretation: valueInterp } : {}),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
proofDecode = {
|
|
178
|
+
error: error instanceof Error ? error.message : String(error),
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// ─── 5. Optional forge-demo (closes the rebuttal loop in one call) ───────
|
|
183
|
+
let forge_demo = null;
|
|
184
|
+
if (input.include_forge_demo) {
|
|
185
|
+
if (!input.tx_hash) {
|
|
186
|
+
forge_demo = {
|
|
187
|
+
skipped: true,
|
|
188
|
+
reason: 'include_forge_demo requires tx_hash (forging needs the TX commitments)',
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
// Pick the most rebuttal-relevant demo amount:
|
|
193
|
+
// - matched flagged artifact's pinned amount (e.g. -2.2M for 2022 claim)
|
|
194
|
+
// - else reuse the cited proof_string V if we successfully decoded one
|
|
195
|
+
// - else default to -1 DERO
|
|
196
|
+
let demoAmount = '-1';
|
|
197
|
+
let demoSource = 'default';
|
|
198
|
+
const flaggedAmount = matched.find((a) => typeof a.demo_amount_dero === 'string')
|
|
199
|
+
?.demo_amount_dero;
|
|
200
|
+
if (flaggedAmount) {
|
|
201
|
+
demoAmount = flaggedAmount;
|
|
202
|
+
demoSource = 'flagged_artifact';
|
|
203
|
+
}
|
|
204
|
+
else if (proofDecode?.value_interpretation?.dero) {
|
|
205
|
+
demoAmount = proofDecode.value_interpretation.dero;
|
|
206
|
+
demoSource = 'proof_string_v';
|
|
207
|
+
}
|
|
208
|
+
try {
|
|
209
|
+
const forged = await forgeDemoProof(rpc, {
|
|
210
|
+
tx_hash: input.tx_hash,
|
|
211
|
+
ring_slot: 0,
|
|
212
|
+
amount_dero: demoAmount,
|
|
213
|
+
});
|
|
214
|
+
forge_demo = {
|
|
215
|
+
skipped: false,
|
|
216
|
+
forged_proof_string: forged.forged_proof_string,
|
|
217
|
+
target_amount: forged.target_amount,
|
|
218
|
+
ring_slot: forged.ring_slot,
|
|
219
|
+
ring_size: forged.ring_size,
|
|
220
|
+
ring_receiver_address: forged.ring_receiver_address,
|
|
221
|
+
math: forged.math,
|
|
222
|
+
self_check: forged.self_check,
|
|
223
|
+
explorer_display_amount: forged.explorer_display_amount,
|
|
224
|
+
demo_amount_source: demoSource,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
forge_demo = {
|
|
229
|
+
skipped: true,
|
|
230
|
+
reason: `forge failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// ─── 6. Assemble chain_facts payload ─────────────────────────────────────
|
|
236
|
+
const blockHeaderTopo = stepValue(chain, 'block_header_by_topo');
|
|
237
|
+
const blockHeaderHash = stepValue(chain, 'block_header_by_hash');
|
|
238
|
+
const txResult = stepValue(chain, 'get_transaction');
|
|
239
|
+
const chainFacts = (() => {
|
|
240
|
+
const header = blockHeaderTopo?.block_header ?? blockHeaderHash?.block_header;
|
|
241
|
+
let txStatus;
|
|
242
|
+
if (txResult?.txs && txResult.txs.length > 0) {
|
|
243
|
+
const t = txResult.txs[0];
|
|
244
|
+
const accepted = !!t.valid_block && t.valid_block !== '';
|
|
245
|
+
txStatus = {
|
|
246
|
+
accepted,
|
|
247
|
+
in_pool: !!t.in_pool,
|
|
248
|
+
block_height: typeof t.block_height === 'number' ? t.block_height : null,
|
|
249
|
+
valid_block: t.valid_block ?? null,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
if (!header && !txStatus)
|
|
253
|
+
return null;
|
|
254
|
+
return {
|
|
255
|
+
...(header ? { block_header: header } : {}),
|
|
256
|
+
...(txStatus ? { transaction_status: txStatus } : {}),
|
|
257
|
+
};
|
|
258
|
+
})();
|
|
259
|
+
// ─── 7. Verdict + narrative + related_docs ────────────────────────────────
|
|
260
|
+
const verdict = matched.length > 0 ? 'cited_in_false_claim' : 'clean';
|
|
261
|
+
const enrichment = enrichWithFlaggedArtifacts({
|
|
262
|
+
topoheight: input.topoheight,
|
|
263
|
+
block_hash: input.block_hash,
|
|
264
|
+
tx_hash: input.tx_hash,
|
|
265
|
+
proof_string: input.proof_string,
|
|
266
|
+
}, relatedDocsFor('audit_chain_artifact_claim'));
|
|
267
|
+
const related_docs = enrichment?.related_docs ?? relatedDocsFor('audit_chain_artifact_claim') ?? [];
|
|
268
|
+
const context_note = enrichment?.context_note ?? null;
|
|
269
|
+
const matched_artifacts = matched.map((a) => ({
|
|
270
|
+
id: a.id,
|
|
271
|
+
matched_by: a.matchers
|
|
272
|
+
.filter((m) => {
|
|
273
|
+
if (m.kind === 'topoheight')
|
|
274
|
+
return input.topoheight === m.value;
|
|
275
|
+
if (m.kind === 'block_hash') {
|
|
276
|
+
return !!input.block_hash && input.block_hash.toLowerCase() === m.value.toLowerCase();
|
|
277
|
+
}
|
|
278
|
+
if (m.kind === 'tx_hash') {
|
|
279
|
+
return !!input.tx_hash && input.tx_hash.toLowerCase() === m.value.toLowerCase();
|
|
280
|
+
}
|
|
281
|
+
if (m.kind === 'proof_string')
|
|
282
|
+
return input.proof_string === m.value;
|
|
283
|
+
return false;
|
|
284
|
+
})
|
|
285
|
+
.map((m) => m.kind),
|
|
286
|
+
}));
|
|
287
|
+
const narrative = buildNarrative(verdict, input, matched, chainFacts, proofDecode, forge_demo);
|
|
288
|
+
return {
|
|
289
|
+
verdict,
|
|
290
|
+
inputs: input,
|
|
291
|
+
matched_artifacts,
|
|
292
|
+
context_note,
|
|
293
|
+
chain_facts: chainFacts,
|
|
294
|
+
proof_decode: proofDecode,
|
|
295
|
+
forge_demo,
|
|
296
|
+
narrative,
|
|
297
|
+
related_docs,
|
|
298
|
+
_diagnostics: {
|
|
299
|
+
step_latencies: stepLatencies(chain),
|
|
300
|
+
halted_at: chain.haltedAt,
|
|
301
|
+
total_ms: chain.totalMs,
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=audit-chain-artifact-claim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-chain-artifact-claim.js","sourceRoot":"","sources":["../../src/composites/audit-chain-artifact-claim.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `diagnose_chain_health` — Phase C composite #1.
|
|
3
|
+
*
|
|
4
|
+
* Decorator-style composite that replaces four agent round-trips
|
|
5
|
+
* (`DERO.Ping` + `DERO.GetInfo` + `DERO.GetHeight` + `DERO.GetTxPool`) and
|
|
6
|
+
* the "what does this field mean?" docs lookup with a single narrative
|
|
7
|
+
* response carrying chain metadata, mempool snapshot, narrative summary,
|
|
8
|
+
* and curated docs citations.
|
|
9
|
+
*
|
|
10
|
+
* Design contract § 1 (lowest-risk composite, ships
|
|
11
|
+
* first to prove the composite plumbing — shared utils + flow test pattern
|
|
12
|
+
* + smoke assertions — end-to-end).
|
|
13
|
+
*
|
|
14
|
+
* Failure model:
|
|
15
|
+
* - `DERO.Ping` is the only required step. Its failure halts the chain
|
|
16
|
+
* and the handler throws so `withStructuredErrors` surfaces a
|
|
17
|
+
* structured `RPC_UNREACHABLE` error.
|
|
18
|
+
* - `DERO.GetInfo`, `DERO.GetHeight`, and `DERO.GetTxPool` are
|
|
19
|
+
* non-required. Their failures degrade `status` to `partial` and
|
|
20
|
+
* leave the corresponding response field null, but the composite
|
|
21
|
+
* still returns a useful payload.
|
|
22
|
+
*/
|
|
23
|
+
import { z } from 'zod';
|
|
24
|
+
import { type DeroDaemonRpc } from './_shared.js';
|
|
25
|
+
export declare const diagnoseChainHealthInputSchema: {
|
|
26
|
+
readonly include_tx_pool: z.ZodOptional<z.ZodBoolean>;
|
|
27
|
+
};
|
|
28
|
+
type DiagnoseInput = {
|
|
29
|
+
include_tx_pool?: boolean;
|
|
30
|
+
};
|
|
31
|
+
type DiagnoseStatus = 'healthy' | 'lagging' | 'partial' | 'unreachable';
|
|
32
|
+
type DiagnoseSignal = {
|
|
33
|
+
key: string;
|
|
34
|
+
value: string | number;
|
|
35
|
+
note?: string;
|
|
36
|
+
};
|
|
37
|
+
export declare function diagnoseChainHealth(rpc: DeroDaemonRpc, args: DiagnoseInput): Promise<{
|
|
38
|
+
status: DiagnoseStatus;
|
|
39
|
+
narrative: string;
|
|
40
|
+
signals: DiagnoseSignal[];
|
|
41
|
+
chain: {
|
|
42
|
+
topoheight: number;
|
|
43
|
+
stableheight: number | null;
|
|
44
|
+
height: number | null;
|
|
45
|
+
network: string | null;
|
|
46
|
+
version: string | null;
|
|
47
|
+
difficulty: string | number | null;
|
|
48
|
+
total_supply: string | number | null;
|
|
49
|
+
} | null;
|
|
50
|
+
mempool: {
|
|
51
|
+
pending: number;
|
|
52
|
+
sample: string[];
|
|
53
|
+
} | null;
|
|
54
|
+
_diagnostics: {
|
|
55
|
+
step_latency_ms: Record<string, number>;
|
|
56
|
+
total_ms: number;
|
|
57
|
+
halted_at: string | null;
|
|
58
|
+
include_tx_pool: boolean;
|
|
59
|
+
};
|
|
60
|
+
} & {
|
|
61
|
+
related_docs?: import("../citations.js").DeroCitation[];
|
|
62
|
+
}>;
|
|
63
|
+
export {};
|
|
64
|
+
//# sourceMappingURL=diagnose-chain-health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnose-chain-health.d.ts","sourceRoot":"","sources":["../../src/composites/diagnose-chain-health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAML,KAAK,aAAa,EACnB,MAAM,cAAc,CAAA;AAErB,eAAO,MAAM,8BAA8B;;CAKjC,CAAA;AAEV,KAAK,aAAa,GAAG;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AAyBlD,KAAK,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAA;AAEvE,KAAK,cAAc,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AA4E5E,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;GA+DhF"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `diagnose_chain_health` — Phase C composite #1.
|
|
3
|
+
*
|
|
4
|
+
* Decorator-style composite that replaces four agent round-trips
|
|
5
|
+
* (`DERO.Ping` + `DERO.GetInfo` + `DERO.GetHeight` + `DERO.GetTxPool`) and
|
|
6
|
+
* the "what does this field mean?" docs lookup with a single narrative
|
|
7
|
+
* response carrying chain metadata, mempool snapshot, narrative summary,
|
|
8
|
+
* and curated docs citations.
|
|
9
|
+
*
|
|
10
|
+
* Design contract § 1 (lowest-risk composite, ships
|
|
11
|
+
* first to prove the composite plumbing — shared utils + flow test pattern
|
|
12
|
+
* + smoke assertions — end-to-end).
|
|
13
|
+
*
|
|
14
|
+
* Failure model:
|
|
15
|
+
* - `DERO.Ping` is the only required step. Its failure halts the chain
|
|
16
|
+
* and the handler throws so `withStructuredErrors` surfaces a
|
|
17
|
+
* structured `RPC_UNREACHABLE` error.
|
|
18
|
+
* - `DERO.GetInfo`, `DERO.GetHeight`, and `DERO.GetTxPool` are
|
|
19
|
+
* non-required. Their failures degrade `status` to `partial` and
|
|
20
|
+
* leave the corresponding response field null, but the composite
|
|
21
|
+
* still returns a useful payload.
|
|
22
|
+
*/
|
|
23
|
+
import { z } from 'zod';
|
|
24
|
+
import { attachCitations, runChain, stepLatencies, stepValue, } from './_shared.js';
|
|
25
|
+
export const diagnoseChainHealthInputSchema = {
|
|
26
|
+
include_tx_pool: z
|
|
27
|
+
.boolean()
|
|
28
|
+
.optional()
|
|
29
|
+
.describe('Include mempool snapshot in narrative and response. Default true.'),
|
|
30
|
+
};
|
|
31
|
+
const LAG_DEPTH_LAGGING_THRESHOLD = 50;
|
|
32
|
+
/**
|
|
33
|
+
* Pure function: turn the three RPC payloads (any of which may be null
|
|
34
|
+
* if the corresponding step failed) into a status, narrative, and
|
|
35
|
+
* machine-readable signals block. Kept inside this file because it is
|
|
36
|
+
* tightly coupled to the response shape and is not reused elsewhere.
|
|
37
|
+
*/
|
|
38
|
+
function summarizeChainHealth(info, height, txPool, txPoolRequested) {
|
|
39
|
+
const signals = [];
|
|
40
|
+
if (!info || typeof info.topoheight !== 'number' || typeof info.stableheight !== 'number') {
|
|
41
|
+
return {
|
|
42
|
+
status: 'partial',
|
|
43
|
+
narrative: 'Daemon ping succeeded but chain info was unavailable; only liveness can be confirmed. Inspect daemon logs and retry.',
|
|
44
|
+
signals,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const lagDepth = info.topoheight - info.stableheight;
|
|
48
|
+
signals.push({ key: 'topoheight', value: info.topoheight });
|
|
49
|
+
signals.push({ key: 'stableheight', value: info.stableheight });
|
|
50
|
+
signals.push({
|
|
51
|
+
key: 'lag_depth',
|
|
52
|
+
value: lagDepth,
|
|
53
|
+
note: 'topoheight minus stableheight; values above 50 suggest the node is catching up',
|
|
54
|
+
});
|
|
55
|
+
if (info.network)
|
|
56
|
+
signals.push({ key: 'network', value: info.network });
|
|
57
|
+
if (info.version)
|
|
58
|
+
signals.push({ key: 'version', value: info.version });
|
|
59
|
+
if (height && typeof height.topoheight === 'number' && height.topoheight !== info.topoheight) {
|
|
60
|
+
signals.push({
|
|
61
|
+
key: 'topoheight_drift',
|
|
62
|
+
value: height.topoheight - info.topoheight,
|
|
63
|
+
note: 'GetHeight reported a different topoheight than GetInfo; values within +/-1 are normal between RPC calls',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
let status = 'healthy';
|
|
67
|
+
const narrativeParts = [];
|
|
68
|
+
if (lagDepth > LAG_DEPTH_LAGGING_THRESHOLD) {
|
|
69
|
+
status = 'lagging';
|
|
70
|
+
narrativeParts.push(`Chain shows a lag depth of ${lagDepth} blocks between topoheight (${info.topoheight}) and stableheight (${info.stableheight}); typical depth is under ${LAG_DEPTH_LAGGING_THRESHOLD}, so the node may be catching up.`);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
narrativeParts.push(`Chain appears healthy on ${info.network ?? 'unknown network'} (version ${info.version ?? 'unknown'}): topoheight ${info.topoheight}, stableheight ${info.stableheight}, lag depth ${lagDepth}.`);
|
|
74
|
+
}
|
|
75
|
+
if (!txPoolRequested) {
|
|
76
|
+
narrativeParts.push('Mempool snapshot was skipped by request (include_tx_pool=false).');
|
|
77
|
+
}
|
|
78
|
+
else if (!txPool) {
|
|
79
|
+
if (status === 'healthy')
|
|
80
|
+
status = 'partial';
|
|
81
|
+
narrativeParts.push('Mempool snapshot failed; mempool state is unknown for this report.');
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
const pending = Array.isArray(txPool.tx_hashes) ? txPool.tx_hashes.length : 0;
|
|
85
|
+
signals.push({ key: 'mempool_pending', value: pending });
|
|
86
|
+
narrativeParts.push(pending === 0
|
|
87
|
+
? 'Mempool is empty.'
|
|
88
|
+
: `Mempool has ${pending} pending transaction${pending === 1 ? '' : 's'}.`);
|
|
89
|
+
}
|
|
90
|
+
return { status, narrative: narrativeParts.join(' '), signals };
|
|
91
|
+
}
|
|
92
|
+
export async function diagnoseChainHealth(rpc, args) {
|
|
93
|
+
const includeTxPool = args.include_tx_pool !== false;
|
|
94
|
+
const steps = [
|
|
95
|
+
{ name: 'ping', required: true, fn: () => rpc('DERO.Ping') },
|
|
96
|
+
{ name: 'info', required: false, fn: () => rpc('DERO.GetInfo') },
|
|
97
|
+
{ name: 'height', required: false, fn: () => rpc('DERO.GetHeight') },
|
|
98
|
+
...(includeTxPool
|
|
99
|
+
? [{ name: 'tx_pool', required: false, fn: () => rpc('DERO.GetTxPool') }]
|
|
100
|
+
: []),
|
|
101
|
+
];
|
|
102
|
+
const chain = await runChain(steps);
|
|
103
|
+
if (chain.haltedAt === 'ping') {
|
|
104
|
+
const pingResult = chain.results.find((r) => r.name === 'ping');
|
|
105
|
+
const detail = pingResult?.error?.message ?? 'unknown error';
|
|
106
|
+
// `withStructuredErrors` classifies this message into RPC_UNREACHABLE.
|
|
107
|
+
throw new Error(`fetch failed: ${detail}`);
|
|
108
|
+
}
|
|
109
|
+
const info = stepValue(chain, 'info');
|
|
110
|
+
const height = stepValue(chain, 'height');
|
|
111
|
+
const txPool = includeTxPool ? stepValue(chain, 'tx_pool') : null;
|
|
112
|
+
const { status, narrative, signals } = summarizeChainHealth(info, height, txPool, includeTxPool);
|
|
113
|
+
const chainData = info && typeof info.topoheight === 'number'
|
|
114
|
+
? {
|
|
115
|
+
topoheight: info.topoheight,
|
|
116
|
+
stableheight: info.stableheight ?? null,
|
|
117
|
+
height: info.height ?? null,
|
|
118
|
+
network: info.network ?? null,
|
|
119
|
+
version: info.version ?? null,
|
|
120
|
+
difficulty: info.difficulty ?? null,
|
|
121
|
+
total_supply: info.total_supply ?? null,
|
|
122
|
+
}
|
|
123
|
+
: null;
|
|
124
|
+
const mempool = txPool
|
|
125
|
+
? {
|
|
126
|
+
pending: Array.isArray(txPool.tx_hashes) ? txPool.tx_hashes.length : 0,
|
|
127
|
+
sample: (txPool.tx_hashes ?? []).slice(0, 5),
|
|
128
|
+
}
|
|
129
|
+
: null;
|
|
130
|
+
return attachCitations({
|
|
131
|
+
status,
|
|
132
|
+
narrative,
|
|
133
|
+
signals,
|
|
134
|
+
chain: chainData,
|
|
135
|
+
mempool,
|
|
136
|
+
_diagnostics: {
|
|
137
|
+
step_latency_ms: stepLatencies(chain),
|
|
138
|
+
total_ms: chain.totalMs,
|
|
139
|
+
halted_at: chain.haltedAt,
|
|
140
|
+
include_tx_pool: includeTxPool,
|
|
141
|
+
},
|
|
142
|
+
}, 'diagnose_chain_health');
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=diagnose-chain-health.js.map
|