File size: 3,763 Bytes
0a93d9c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// SPDX-License-Identifier: (Apache-2.0 OR AGPL-3.0 OR BSL-1.1)
// Copyright 2026 Bel Esprit D'Accord Irrevocable Trust (EIN: 42-697643)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// OR
//
// Licensed under the GNU Affero General Public License, Version 3.0
// (the "AGPL"); you may not use this file except in compliance with the AGPL.
// You may obtain a copy of the AGPL at
//
//     https://www.gnu.org/licenses/agpl-3.0.html
//
// OR
//
// Licensed under the Business Source License 1.1 (BSL-1.1);
// converts to Apache-2.0 after 4 years. See LICENSE-BSL for terms.
pragma solidity ^0.8.24;

/// @title Groth16 Verifier for ALGORITHM_ENGINE
/// @notice Auto-generated from snarkjs zkey export solidityverifier
/// @dev This file should be replaced with actual output from:
/// snarkjs zkey export solidityverifier engine_final.zkey Groth16Verifier.sol
interface IGroth16Verifier {
    function verifyProof(

        uint[2] calldata _pA,

        uint[2][2] calldata _pB,

        uint[2] calldata _pC,

        uint[2] calldata _pubSignals

    ) external view returns (bool);
}

/// @title ALGORITHM_ENGINE Anchor Contract
/// @notice Ingress router for Ledge SDK event-driven workflows
/// @dev Only accepts objectives with valid Groth16 proofs
contract AlgorithmEngineAnchor {
    IGroth16Verifier public immutable verifier;

    /// @notice Tracks executed objectives to prevent replay
    mapping(uint256 => bool) public executedObjectives;

    /// @notice Emitted when objective is committed to audit chain
    event ObjectiveCommitted(

        uint256 indexed resultHash,

        uint256 indexed priority,

        uint256 timestamp

    );

    error InvalidObjectiveProof();
    error ObjectiveAlreadyExecuted();

    constructor(address _verifierAddress) {
        verifier = IGroth16Verifier(_verifierAddress);
    }

    /// @notice Commits a verified objective to the Ledge audit chain
    /// @param pA Groth16 proof point A (G1)
    /// @param pB Groth16 proof point B (G2)
    /// @param pC Groth16 proof point C (G1)
    /// @param resultHash Public output 0 from Circom (Poseidon hash)
    /// @param priority Public input 1 from Circom (objective priority)
    function commitObjective(

        uint[2] calldata pA,

        uint[2][2] calldata pB,

        uint[2] calldata pC,

        uint256 resultHash,

        uint256 priority

    ) external {
        if (executedObjectives[resultHash]) {
            revert ObjectiveAlreadyExecuted();
        }

        // snarkjs orders: publicSignals = [resultHash, priority]
        uint[2] memory pubSignals = [resultHash, priority];

        bool isValid = verifier.verifyProof(pA, pB, pC, pubSignals);
        if (!isValid) {
            revert InvalidObjectiveProof();
        }

        executedObjectives[resultHash] = true;

        emit ObjectiveCommitted(resultHash, priority, block.timestamp);
    }

    /// @notice Batch commit multiple objectives
    function commitObjectives(

        uint[2][] calldata pAs,

        uint[2][2][] calldata pBs,

        uint[2][] calldata pCs,

        uint256[] calldata resultHashes,

        uint256[] calldata priorities

    ) external {
        require(pAs.length == pBs.length && pBs.length == pCs.length);
        require(pAs.length == resultHashes.length && resultHashes.length == priorities.length);

        for (uint i = 0; i < pAs.length; i++) {
            commitObjective(pAs[i], pBs[i], pCs[i], resultHashes[i], priorities[i]);
        }
    }
}