Skip to main content
Attested compute allows to perform a computation on a handle completely off-chain and get the decryption attestation containing decryption result and attestation. Only handles that are allowed with e.allow() or e.reveal() can be used in computation. The attestation can then be verified on-chain to perform certain on-chain actions, avoiding unnecessary transaction.

Getting Started

Take this example contract that holds an encrypted credit score of a user, to determine whether they’re eligible for a loan:
import {euint256, e, ebool, inco} from "@inco/lightning/src/Lib.sol";
import {DecryptionAttestation} from "@inco/lightning/src/lightning-parts/DecryptionAttester.types.sol";
import {asBool} from "@inco/lightning/src/shared/TypeUtils.sol";

contract TestAttestedCompute {
    euint256 hiddenCreditScore;

    constructor(address owner) payable {
        require(msg.value == inco.getFee(), "Fee not paid");
        hiddenCreditScore = e.asEuint256(800);
        e.allow(hiddenCreditScore, address(this));
        e.allow(hiddenCreditScore, owner);
    }

    function GetHandle() external returns (euint256) {
        return hiddenCreditScore;
    }

    function SubmitCreditCheck(
        DecryptionAttestation memory decryption,
        bytes[] memory signatures
    ) external {
        // Verify covalidator signatures over the attested result
        require(
            inco.incoVerifier().isValidDecryptionAttestation(decryption, signatures),
            "Invalid signature"
        );

        // Recompute the expected "creditScore >= 700" handle on-chain
        require(
            ebool.unwrap(e.ge(hiddenCreditScore, 700)) == decryption.handle,
            "Computed handle mismatch"
        );

        // Check that the decrypted boolean is true
        require(asBool(decryption.value) == true, "Credit check failed");

        // Credit check passed - proceed with loan approval
    }
}
Presume we want to know whether the credit score is greater than or equal 700 without sending an additional transaction. We can do that by calling attestedCompute (similar to Attested Decrypt):
import { Lightning } from '@inco/js/lite';
import { getViemChain, supportedChains, type HexString } from '@inco/js';
import { AttestedComputeSupportedOps } from '@inco/js/lite';
import { createWalletClient, custom } from 'viem'

const zap = await Lightning.latest('testnet', supportedChains.baseSepolia);

//Connect to Metamask or other wallet provider
const walletClient = createWalletClient({
  chain: getViemChain(supportedChains.baseSepolia),
  transport: custom(window.ethereum!)
})

// Retrieve the hiddenCreditScore handle from the contract by calling GetHandle(), e.g. using viem
const hiddenCreditScore = '0x<handle>' as HexString;

// isGreaterOrEqual = hiddenCreditScore >= 700
const isGreaterOrEqual = await zap.attestedCompute(
  walletClient,
  hiddenCreditScore,
  AttestedComputeSupportedOps.Ge,
  700n,
);

const creditScoreSufficient = isGreaterOrEqual.plaintext.value; // always boolean
Which is equivalent to:
ebool creditScoreSufficient = e.ge(hiddenCreditScore, 700);
isGreaterOrEqual also contains a signature from covalidator attesting to the computation, which can be used to submit decryption back on-chain, even if the handle doesn’t exist on chain yet.

Supported operations

NameOpTypeReturns
EqualAttestedComputeSupportedOps.EqScalar Binary*bool
Not equalAttestedComputeSupportedOps.NeScalar Binary*bool
Greater than or equalAttestedComputeSupportedOps.GeScalar Binary*bool
Greater thanAttestedComputeSupportedOps.GtScalar Binary*bool
Less than or equalAttestedComputeSupportedOps.LeScalar Binary*bool
Less thanAttestedComputeSupportedOps.LtScalar Binary*bool
  • Scalar binary operation - operation that takes in two operands, one of which is a handle and the second one is a number (aka scalar).

Compute with Allowance Voucher/Session Key

Compute on a handle can be performed with a session key instead of a wallet provider using sessionKeyAttestedCompute(), see Allowance Voucher.