inco-svm

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Inco SVM — Confidential Computing on Solana

Inco SVM — Solana上的保密计算

Inco Lightning is a confidentiality layer for Solana that enables developers to build applications where sensitive data remains encrypted even during computation. It uses Trusted Execution Environments (TEEs) to deliver verifiable confidential compute — no new chain, no new wallet required.
Note: Inco SVM is currently in beta on Solana devnet. Features are subject to change.
Inco Lightning是Solana的一个保密层,开发者可借助它构建敏感数据在计算过程中仍保持加密状态的应用。它采用可信执行环境(TEEs)来提供可验证的保密计算——无需新链,也无需新钱包。
注意: Inco SVM目前处于Solana devnet的测试版。功能可能会有所变动。

Overview

概述

  • Encrypted Types
    Euint128
    and
    Ebool
    handles representing encrypted values stored off-chain
  • Homomorphic Operations — Arithmetic, comparison, bitwise, and control flow on encrypted data via CPI
  • Access Control — Allowance PDA system for granting per-handle decryption permissions
  • Attested Decryption — Ed25519 signature-verified decryption through TEE covalidators
  • Confidential SPL Token — Privacy-preserving token standard with encrypted balances and transfers
  • Client SDK
    @inco/solana-sdk
    for encryption, decryption, and utility helpers
  • 加密类型
    Euint128
    Ebool
    用于表示存储在链下的加密值
  • 同态运算 — 通过CPI对加密数据进行算术、比较、位运算以及流程控制操作
  • 访问控制 — 基于Allowance PDA系统,为每个句柄授予解密权限
  • 经认证的解密 — 通过TEE协同验证节点进行Ed25519签名验证解密
  • 保密SPL代币 — 支持加密余额和转账的隐私保护代币标准
  • 客户端SDK
    @inco/solana-sdk
    提供加密、解密及实用工具函数

Architecture

架构

Client                    Solana Program              Inco Covalidator (TEE)
  │                            │                              │
  ├─ encryptValue() ──────────►│                              │
  │                            ├─ CPI: new_euint128 ─────────►│
  │                            │◄─── handle (u128) ──────────┤
  │                            ├─ CPI: e_add / e_sub / ... ──►│
  │                            │◄─── result handle ──────────┤
  │                            ├─ CPI: allow() ──────────────►│
  │                            │                              │
  ├─ decrypt([handle]) ───────────────────────────────────────►│
  │◄─── plaintext + Ed25519 attestation ──────────────────────┤
Inco Lightning Program ID:
5sjEbPiqgZrYwR31ahR6Uk9wf5awoX61YGg7jExQSwaj
Client                    Solana Program              Inco Covalidator (TEE)
  │                            │                              │
  ├─ encryptValue() ──────────►│                              │
  │                            ├─ CPI: new_euint128 ─────────►│
  │                            │◄─── handle (u128) ──────────┤
  │                            ├─ CPI: e_add / e_sub / ... ──►│
  │                            │◄─── result handle ──────────┤
  │                            ├─ CPI: allow() ──────────────►│
  │                            │                              │
  ├─ decrypt([handle]) ───────────────────────────────────────►│
  │◄─── plaintext + Ed25519 attestation ──────────────────────┤
Inco Lightning程序ID:
5sjEbPiqgZrYwR31ahR6Uk9wf5awoX61YGg7jExQSwaj

Quick Start

快速开始

Installation

安装

Rust Crate (on-chain):
Add to your
Cargo.toml
:
toml
[dependencies]
inco-lightning = { version = "0.1", features = ["cpi"] }
Add to
Anchor.toml
:
toml
[programs.devnet]
inco_lightning = "5sjEbPiqgZrYwR31ahR6Uk9wf5awoX61YGg7jExQSwaj"
JavaScript SDK (client-side):
bash
npm install @inco/solana-sdk
Rust Crate(链上):
添加到你的
Cargo.toml
:
toml
[dependencies]
inco-lightning = { version = "0.1", features = ["cpi"] }
添加到
Anchor.toml
:
toml
[programs.devnet]
inco_lightning = "5sjEbPiqgZrYwR31ahR6Uk9wf5awoX61YGg7jExQSwaj"
JavaScript SDK(客户端):
bash
npm install @inco/solana-sdk

Basic Program Setup

基础程序设置

rust
use anchor_lang::prelude::*;
use inco_lightning::cpi::accounts::Operation;
use inco_lightning::cpi::{e_add, e_sub, e_ge, e_select, new_euint128, as_euint128};
use inco_lightning::types::{Euint128, Ebool};
use inco_lightning::ID as INCO_LIGHTNING_ID;

declare_id!("YOUR_PROGRAM_ID");

#[program]
pub mod my_confidential_program {
    use super::*;

    pub fn deposit(ctx: Context<Deposit>, ciphertext: Vec<u8>) -> Result<()> {
        let cpi_ctx = CpiContext::new(
            ctx.accounts.inco_lightning_program.to_account_info(),
            Operation {
                signer: ctx.accounts.authority.to_account_info(),
            },
        );

        // Create encrypted handle from client ciphertext
        let amount: Euint128 = new_euint128(cpi_ctx.clone(), ciphertext, 0)?;

        // Add to existing balance
        let new_balance = e_add(cpi_ctx, ctx.accounts.vault.balance, amount, 0)?;
        ctx.accounts.vault.balance = new_balance;

        Ok(())
    }
}

#[derive(Accounts)]
pub struct Deposit<'info> {
    #[account(mut)]
    pub authority: Signer<'info>,
    #[account(mut)]
    pub vault: Account<'info, Vault>,
    /// CHECK: Inco Lightning program
    #[account(address = INCO_LIGHTNING_ID)]
    pub inco_lightning_program: AccountInfo<'info>,
}

#[account]
pub struct Vault {
    pub balance: Euint128,
}
rust
use anchor_lang::prelude::*;
use inco_lightning::cpi::accounts::Operation;
use inco_lightning::cpi::{e_add, e_sub, e_ge, e_select, new_euint128, as_euint128};
use inco_lightning::types::{Euint128, Ebool};
use inco_lightning::ID as INCO_LIGHTNING_ID;

declare_id!("YOUR_PROGRAM_ID");

#[program]
pub mod my_confidential_program {
    use super::*;

    pub fn deposit(ctx: Context<Deposit>, ciphertext: Vec<u8>) -> Result<()> {
        let cpi_ctx = CpiContext::new(
            ctx.accounts.inco_lightning_program.to_account_info(),
            Operation {
                signer: ctx.accounts.authority.to_account_info(),
            },
        );

        // Create encrypted handle from client ciphertext
        let amount: Euint128 = new_euint128(cpi_ctx.clone(), ciphertext, 0)?;

        // Add to existing balance
        let new_balance = e_add(cpi_ctx, ctx.accounts.vault.balance, amount, 0)?;
        ctx.accounts.vault.balance = new_balance;

        Ok(())
    }
}

#[derive(Accounts)]
pub struct Deposit<'info> {
    #[account(mut)]
    pub authority: Signer<'info>,
    #[account(mut)]
    pub vault: Account<'info, Vault>,
    /// CHECK: Inco Lightning program
    #[account(address = INCO_LIGHTNING_ID)]
    pub inco_lightning_program: AccountInfo<'info>,
}

#[account]
pub struct Vault {
    pub balance: Euint128,
}

Basic Client Usage

基础客户端使用

typescript
import { encryptValue } from "@inco/solana-sdk/encryption";
import { decrypt } from "@inco/solana-sdk/attested-decrypt";

// Encrypt a value before sending to program
const encrypted = await encryptValue(1000n);

await program.methods
  .deposit(Buffer.from(encrypted, "hex"))
  .accounts({ authority: wallet.publicKey, vault: vaultPda, incoLightningProgram: INCO_LIGHTNING_ID })
  .rpc();

// Decrypt a handle (requires wallet signature)
const result = await decrypt([handleString], {
  address: wallet.publicKey,
  signMessage: wallet.signMessage,
});
console.log("Decrypted:", result.plaintexts[0]);
typescript
import { encryptValue } from "@inco/solana-sdk/encryption";
import { decrypt } from "@inco/solana-sdk/attested-decrypt";

// Encrypt a value before sending to program
const encrypted = await encryptValue(1000n);

await program.methods
  .deposit(Buffer.from(encrypted, "hex"))
  .accounts({ authority: wallet.publicKey, vault: vaultPda, incoLightningProgram: INCO_LIGHTNING_ID })
  .rpc();

// Decrypt a handle (requires wallet signature)
const result = await decrypt([handleString], {
  address: wallet.publicKey,
  signMessage: wallet.signMessage,
});
console.log("Decrypted:", result.plaintexts[0]);

Encrypted Types & Handles

加密类型与句柄

Handles are 128-bit references to encrypted values stored off-chain in the covalidator network.
TypeDescriptionRust Definition
Euint128
Encrypted unsigned 128-bit integer
pub struct Euint128(pub u128)
Ebool
Encrypted boolean
pub struct Ebool(pub u128)
Store handles directly in account structs:
rust
#[account]
pub struct ConfidentialAccount {
    pub balance: Euint128,
    pub is_active: Ebool,
}
句柄是指向存储在协同验证节点网络链下的加密值的128位引用。
类型描述Rust定义
Euint128
加密的无符号128位整数
pub struct Euint128(pub u128)
Ebool
加密的布尔值
pub struct Ebool(pub u128)
直接在账户结构体中存储句柄:
rust
#[account]
pub struct ConfidentialAccount {
    pub balance: Euint128,
    pub is_active: Ebool,
}

Input Functions

输入函数

FunctionDescription
new_euint128(ctx, ciphertext, input_type)
Create from client-encrypted ciphertext
new_ebool(ctx, ciphertext, input_type)
Create encrypted bool from ciphertext
as_euint128(ctx, value)
Trivial encryption of plaintext u128 (for constants like zero)
as_ebool(ctx, value)
Trivial encryption of plaintext bool
函数描述
new_euint128(ctx, ciphertext, input_type)
从客户端加密的密文创建句柄
new_ebool(ctx, ciphertext, input_type)
从密文创建加密布尔值
as_euint128(ctx, value)
对明文u128进行简单加密(用于零等常量)
as_ebool(ctx, value)
对明文布尔值进行简单加密

Operations on Encrypted Data

加密数据运算

All operations require a CPI context and return new handles.
rust
let cpi_ctx = CpiContext::new(
    ctx.accounts.inco_lightning_program.to_account_info(),
    Operation { signer: ctx.accounts.authority.to_account_info() },
);
let result = e_add(cpi_ctx, a, b, 0)?;
The last parameter (
scalar_byte
) is
0
for encrypted-encrypted operations,
1
when the left operand is plaintext.
所有运算都需要CPI上下文,并返回新的句柄。
rust
let cpi_ctx = CpiContext::new(
    ctx.accounts.inco_lightning_program.to_account_info(),
    Operation { signer: ctx.accounts.authority.to_account_info() },
);
let result = e_add(cpi_ctx, a, b, 0)?;
最后一个参数(
scalar_byte
)在加密-加密运算时为
0
,当左操作数为明文时为
1

Arithmetic →
Euint128

算术运算 →
Euint128

e_add
,
e_sub
,
e_mul
,
e_rem
e_add
,
e_sub
,
e_mul
,
e_rem

Comparison →
Ebool

比较运算 →
Ebool

e_ge
,
e_gt
,
e_le
,
e_lt
,
e_eq
e_ge
,
e_gt
,
e_le
,
e_lt
,
e_eq

Bitwise →
Euint128

位运算 →
Euint128

e_and
,
e_or
,
e_not
,
e_shl
,
e_shr
e_and
,
e_or
,
e_not
,
e_shl
,
e_shr

Control Flow (Multiplexer)

流程控制(多路复用器)

rust
// Cannot use if/else on encrypted values — use e_select instead
let result = e_select(cpi_ctx, condition, if_true, if_false, 0)?;
rust
// Cannot use if/else on encrypted values — use e_select instead
let result = e_select(cpi_ctx, condition, if_true, if_false, 0)?;

Random Number Generation

随机数生成

rust
let random_value = e_rand(cpi_ctx, 0)?;
See resources/rust-sdk-reference.md for the complete API.
rust
let random_value = e_rand(cpi_ctx, 0)?;
完整API请查看resources/rust-sdk-reference.md

Access Control

访问控制

Decryption permissions are managed through Allowance PDAs derived from
[handle.to_le_bytes(), allowed_address]
.
rust
use inco_lightning::cpi::accounts::Allow;
use inco_lightning::cpi::allow;

let cpi_ctx = CpiContext::new(
    ctx.accounts.inco_lightning_program.to_account_info(),
    Allow {
        allowance_account: ctx.accounts.allowance_account.to_account_info(),
        signer: ctx.accounts.authority.to_account_info(),
        allowed_address: ctx.accounts.user.to_account_info(),
        system_program: ctx.accounts.system_program.to_account_info(),
    },
);
allow(cpi_ctx, handle.0, true, user_pubkey)?;
Important: Operations produce new handles, and allowance PDAs depend on the handle value. You must simulate the transaction first to get the result handle, derive the PDA, then submit with
remaining_accounts
.
See resources/access-control.md for the full simulation-then-submit pattern.
解密权限通过从
[handle.to_le_bytes(), allowed_address]
派生的Allowance PDA进行管理。
rust
use inco_lightning::cpi::accounts::Allow;
use inco_lightning::cpi::allow;

let cpi_ctx = CpiContext::new(
    ctx.accounts.inco_lightning_program.to_account_info(),
    Allow {
        allowance_account: ctx.accounts.allowance_account.to_account_info(),
        signer: ctx.accounts.authority.to_account_info(),
        allowed_address: ctx.accounts.user.to_account_info(),
        system_program: ctx.accounts.system_program.to_account_info(),
    },
);
allow(cpi_ctx, handle.0, true, user_pubkey)?;
重要提示: 运算会生成新的句柄,而Allowance PDA依赖于句柄值。你必须先模拟交易以获取结果句柄,派生PDA,然后通过
remaining_accounts
提交交易。
完整的“先模拟再提交”模式请查看resources/access-control.md

Attested Decryption

经认证的解密

Two modes:
ModePurposeReturns
Attested RevealDisplay values in UI
result.plaintexts
Attested DecryptVerify values on-chain
result.ed25519Instructions
+ program IX
typescript
import { decrypt } from "@inco/solana-sdk/attested-decrypt";

const result = await decrypt([handle], {
  address: wallet.publicKey,
  signMessage: wallet.signMessage,
});

// Reveal: use plaintext directly
console.log(result.plaintexts[0]);

// Decrypt: verify on-chain
const tx = new Transaction();
result.ed25519Instructions.forEach(ix => tx.add(ix));
tx.add(yourProgramVerifyInstruction);
await sendTransaction(tx);
On-chain verification:
rust
use inco_lightning::cpi::is_validsignature;
use inco_lightning::cpi::accounts::VerifySignature;

let cpi_ctx = CpiContext::new(
    ctx.accounts.inco_lightning_program.to_account_info(),
    VerifySignature {
        instructions: ctx.accounts.instructions.to_account_info(),
        signer: ctx.accounts.authority.to_account_info(),
    },
);
is_validsignature(cpi_ctx, 1, Some(handles), Some(plaintext_values))?;
两种模式:
模式用途返回内容
经认证的披露在UI中显示值
result.plaintexts
经认证的解密在链上验证值
result.ed25519Instructions
+ 程序指令
typescript
import { decrypt } from "@inco/solana-sdk/attested-decrypt";

const result = await decrypt([handle], {
  address: wallet.publicKey,
  signMessage: wallet.signMessage,
});

// Reveal: use plaintext directly
console.log(result.plaintexts[0]);

// Decrypt: verify on-chain
const tx = new Transaction();
result.ed25519Instructions.forEach(ix => tx.add(ix));
tx.add(yourProgramVerifyInstruction);
await sendTransaction(tx);
链上验证:
rust
use inco_lightning::cpi::is_validsignature;
use inco_lightning::cpi::accounts::VerifySignature;

let cpi_ctx = CpiContext::new(
    ctx.accounts.inco_lightning_program.to_account_info(),
    VerifySignature {
        instructions: ctx.accounts.instructions.to_account_info(),
        signer: ctx.accounts.authority.to_account_info(),
    },
);
is_validsignature(cpi_ctx, 1, Some(handles), Some(plaintext_values))?;

Confidential SPL Token

保密SPL代币

A full privacy-preserving token implementation. See resources/confidential-spl-token.md.
Key functions:
initialize_mint
,
create_account
,
mint_to
,
transfer
,
approve
typescript
// Encrypt and transfer
const encrypted = await encryptValue(500_000_000n);
await program.methods
  .transfer(Buffer.from(encrypted, "hex"), 0)
  .accounts({ source: srcAta, destination: destAta, authority: wallet.publicKey })
  .rpc();
一个完整的隐私保护代币实现。详情请查看resources/confidential-spl-token.md
核心函数:
initialize_mint
,
create_account
,
mint_to
,
transfer
,
approve
typescript
// Encrypt and transfer
const encrypted = await encryptValue(500_000_000n);
await program.methods
  .transfer(Buffer.from(encrypted, "hex"), 0)
  .accounts({ source: srcAta, destination: destAta, authority: wallet.publicKey })
  .rpc();

Best Practices

最佳实践

  1. Always call
    allow()
    after operations
    that produce handles you want to decrypt later
  2. Use
    remaining_accounts
    to pass allowance PDAs and grant access in the same transaction
  3. Grant minimal permissions — only allow specific addresses to decrypt what they need
  4. Use the multiplexer pattern (
    e_select
    ) instead of if/else on encrypted conditions
  5. Trivial encryption only for constants (like zero) — use client-side encryption for sensitive values
  6. Verify the intended handle in attestations to prevent handle-swap attacks
  7. Simulate transactions first to get result handles before deriving allowance PDAs
  1. 在生成需后续解密的句柄的运算后,务必调用
    allow()
  2. 使用
    remaining_accounts
    在同一交易中传递Allowance PDA并授予权限
  3. 授予最小权限 — 仅允许特定地址解密所需内容
  4. 使用多路复用器模式 (
    e_select
    ) 替代对加密条件使用if/else
  5. 仅对常量使用简单加密(如零)—— 敏感值请使用客户端加密
  6. 在认证信息中验证目标句柄 以防止句柄替换攻击
  7. 先模拟交易 在派生Allowance PDA前获取结果句柄

Resources

资源

Skill Structure

技能结构

inco/
├── SKILL.md                              # This file — main reference
├── docs/
│   └── troubleshooting.md                # Common issues and solutions
├── examples/
│   ├── basic-operations/
│   │   └── encrypted-operations.ts       # Arithmetic, comparison, select
│   ├── confidential-spl-token/
│   │   ├── mint-and-transfer.ts          # Mint & transfer confidential tokens
│   │   └── reveal-balance.ts             # Decrypt and reveal token balance
│   └── private-raffle/
│       └── raffle-client.ts              # Full raffle lifecycle client
├── resources/
│   ├── rust-sdk-reference.md             # Complete Rust CPI API
│   ├── js-sdk-reference.md               # JS SDK encryption & decryption
│   ├── access-control.md                 # Allowance PDAs & simulation pattern
│   └── confidential-spl-token.md         # SPL token program reference
└── templates/
    └── inco-svm-setup.ts                 # Starter template with helpers
inco/
├── SKILL.md                              # 本文档——主要参考资料
├── docs/
│   └── troubleshooting.md                # 常见问题与解决方案
├── examples/
│   ├── basic-operations/
│   │   └── encrypted-operations.ts       # 算术、比较、选择运算
│   ├── confidential-spl-token/
│   │   ├── mint-and-transfer.ts          # 铸造并转账保密代币
│   │   └── reveal-balance.ts             # 解密并披露代币余额
│   └── private-raffle/
│       └── raffle-client.ts              # 完整抽奖生命周期客户端
├── resources/
│   ├── rust-sdk-reference.md             # 完整Rust CPI API
│   ├── js-sdk-reference.md               # JS SDK加密与解密
│   ├── access-control.md                 # Allowance PDA与模拟模式
│   └── confidential-spl-token.md         # SPL代币程序参考
└── templates/
    └── inco-svm-setup.ts                 # 包含工具函数的启动模板