@ajna-inc/poe
v0.0.4
Published
Proof of Execution (PoE) protocol for Credo-ts - zero-knowledge proofs of program execution
Downloads
534
Maintainers
Readme
Credo PoE - Proof of Execution Protocol
This package implements the Proof of Execution (PoE) 1.0 protocol for Credo-ts, enabling requesters to ask provers to execute named programs and return zero-knowledge proofs that the program executed correctly on inputs bound to a transaction context — while keeping private inputs confidential.
Features
- 🔐 Zero-Knowledge Proofs: Verify program execution without revealing private inputs
- 🔄 Generic Protocol: Support for multiple programs and proof systems
- 🛡️ Anti-Replay Protection: Strong binding to
{nonce, context_hash, session_id} - 🤝 Capability Negotiation: Optional proposal/accept phases for flexibility
- 🔍 Minimal Disclosure: Proof-only by default, with optional summaries
- 📋 Registry-Based Trust: Local enforcement of verifying keys and program parameters
- 🎯 DIDComm v2: Full integration with DIDComm messaging
Installation
npm install @credo-ts/poe
# or
yarn add @credo-ts/poe
# or
pnpm add @credo-ts/poeQuick Start
1. Setup Agent with PoE Module
import { Agent } from '@credo-ts/core'
import { PoeModule } from '@credo-ts/poe'
const agent = new Agent({
config: {
label: 'My Agent',
walletConfig: {
id: 'my-wallet',
key: 'my-secret-key',
},
},
modules: {
poe: new PoeModule(),
},
})
await agent.initialize()2. Register Programs (Requester Side)
const poeApi = agent.modules.poe
// Register a program in the registry
await poeApi.registerProgram({
program_id: 'vendor.policy.eval.v1',
version: '1',
name: 'Policy Evaluator',
allowed_vk_hashes: ['0xVK_HASH_A', '0xVK_HASH_B'],
public_schema: 'vendor.policy.eval.v1/public@1',
supports_interactive: false,
max_runtime_s: 60,
max_artifact_mb: 8,
})3. Request Proof of Execution (Requester)
const poeSession = await poeApi.requestProofOfExecution(connectionId, {
programs: [
{
program_id: 'vendor.policy.eval.v1',
public_constraints: { params_hash: '0x...' },
inputs: {
schema: 'vendor.policy.eval.v1/inputs@1',
by_value: { ttl_s: 60, policy_ref: 'policy-abc@1' },
},
disclosure: 'proof-only',
},
],
bindingContext: {
nonce: '0x...', // Generated securely
context_hash: '0x...', // Hash of transaction context
session_id: '0x...', // Session identifier
},
expiry: '2025-11-11T14:35:00Z',
})4. Handle Request and Submit Proof (Prover)
// Listen for incoming proof requests
agent.events.on(PoeEventTypes.PoeRequestReceived, async (event) => {
const { poeRecord } = event.payload
// Execute the program and generate proof
const proof = await executeProgram(poeRecord.programId, poeRecord.executionPlan)
// Submit the proof
await poeApi.submitProof(poeRecord.id, {
program_id: poeRecord.programId,
result: 'pass',
public: {
schema: 'vendor.policy.eval.v1/public@1',
nonce: poeRecord.bindingContext.nonce,
context_hash: poeRecord.bindingContext.context_hash,
session_id: poeRecord.bindingContext.session_id,
outputs_hash: '0x...',
vk_hash: '0x...',
},
zk: {
scheme: 'groth16',
circuit_id: 'vendor-policy-eval-v1',
vk_hash: '0x...',
proof_b64: 'base64(proof)...',
},
})
})5. Verify Proof (Requester)
// Listen for proof submissions
agent.events.on(PoeEventTypes.PoeSubmitReceived, async (event) => {
const { poeRecord } = event.payload
// Verification happens automatically in the handler
if (poeRecord.verificationResult?.verified) {
console.log('Proof verified successfully!')
console.log('Receipt:', poeRecord.verificationResult.receipt)
} else {
console.error('Proof verification failed:', poeRecord.verificationResult?.errors)
}
})Protocol Flow
REQUESTER PROVER
| |
|--- RequestPoeMessage --------------> |
| |
|<-- ProposePoeMessage (optional) ---- | [Negotiation]
| |
|--- AcceptPoeMessage (optional) ----> |
| |
| | [Execution]
|<-- SubmitPoeMessage ----------------- |
| |
|--- CompleteMessage ----------------> |
| |Core Concepts
Binding Context
Every PoE instance is bound to a unique context to prevent replay attacks:
interface BindingContext {
nonce: string // 32-byte hex (0x...)
context_hash: string // 32-byte hex (0x...)
session_id: string // 16-byte hex (0x...)
}Disclosure Levels
proof-only: Only the ZK proof is revealed (default)proof+summary: Proof + high-level execution summaryproof+evidence-ref: Proof + encrypted evidence references
Proof Artifacts
interface ProofArtifact {
program_id: string
result: 'pass' | 'fail' | 'partial'
public: PublicOutputs // Binding context + outputs
zk: ZKProof // Zero-knowledge proof
summary?: ExecutionSummary // Optional
evidence_refs?: EvidenceReference[] // Optional
}Advanced Features
Interactive Programs with Challenges
// Send a challenge for multi-round execution
await poeApi.sendChallenge(poeRecordId, {
steps: [{ action: 'perform', payload: ['taskA', 'taskB'] }],
ttl_s: 10,
sequence: 1,
})Delegation to Attesters
// Allow delegation to trusted attesters
await poeApi.requestProofOfExecution(connectionId, {
programs: [...],
bindingContext: {...},
policy: {
allowed_attesters: ['did:key:z6Mk...', 'did:web:attester.example'],
},
})Custom Policies
// Register custom execution policies
await poeApi.registerPolicy({
id: 'my-custom-policy@1',
enforcementPhase: 'post-sign',
enforce: async (agentContext, context) => {
// Custom policy logic
return { passed: true }
},
})API Reference
PoeApi
requestProofOfExecution(connectionId, options)- Request proof executionsubmitProof(poeRecordId, proofArtifact)- Submit proofsendChallenge(poeRecordId, challengeSpec)- Send challengesendComplete(poeRecordId, receipt?)- Signal completionsendProblemReport(poeRecordId, error)- Report problemregisterProgram(metadata)- Register programregisterProofSystem(system)- Register proof systemregisterPolicy(policy)- Register policy
Events
PoeEventTypes.PoeRequestReceived- Proof request receivedPoeEventTypes.PoeProposalReceived- Proposal receivedPoeEventTypes.PoeChallengeReceived- Challenge receivedPoeEventTypes.PoeSubmitReceived- Proof submission receivedPoeEventTypes.PoeCompleted- Protocol completedPoeEventTypes.PoeProblemReport- Problem reportedPoeEventTypes.PoeStateChanged- State changed
Error Codes
Standard error codes as per the PoE spec:
program_not_supported- Program not found in registryinputs_invalid- Invalid program inputsexpired_challenge- Challenge expiredpolicy_violation- Policy constraint violatedinvalid_proof- Proof verification failedvk_unknown- Verifying key not allowedparams_unknown- Program parameters not allowedcontext_mismatch- Binding context mismatchtoo_large- Proof/artifact too largerate_limited- Rate limit exceededattester_unavailable- Attester not available
Security Considerations
- Anti-Replay: Always use fresh, cryptographically secure nonces
- Context Binding: Bind proofs to specific transaction contexts
- Registry Enforcement: Maintain strict allow-lists for VKs and parameters
- Expiry: Set reasonable expiration times for requests
- Policy Validation: Enforce program-specific policies rigorously
- Disclosure: Use
proof-onlyunless additional data is required
Development Status
🚧 This package is currently under active development.
Completed
- ✅ Core data models and message types
- ✅ State machine and protocol flow
- ✅ Registry architecture
- ✅ Anti-replay mechanisms
In Progress
- 🔄 Message handlers
- 🔄 Core services (verification, nonce, context binding)
- 🔄 Proof system integration
Planned
- 📋 Policy enforcement framework
- 📋 HPKE integration for sealed witnesses
- 📋 Multi-round proof support
- 📋 Comprehensive test suite
Contributing
Contributions are welcome! Please see the main Credo repository for contribution guidelines.
Resources
License
Apache License 2.0 - see LICENSE for details.
