inco-svm
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseInco 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 — and
Euint128handles representing encrypted values stored off-chainEbool - 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 — for encryption, decryption, and utility helpers
@inco/solana-sdk
- 加密类型 — 和
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:
5sjEbPiqgZrYwR31ahR6Uk9wf5awoX61YGg7jExQSwajClient 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:
5sjEbPiqgZrYwR31ahR6Uk9wf5awoX61YGg7jExQSwajQuick Start
快速开始
Installation
安装
Rust Crate (on-chain):
Add to your :
Cargo.tomltoml
[dependencies]
inco-lightning = { version = "0.1", features = ["cpi"] }Add to :
Anchor.tomltoml
[programs.devnet]
inco_lightning = "5sjEbPiqgZrYwR31ahR6Uk9wf5awoX61YGg7jExQSwaj"JavaScript SDK (client-side):
bash
npm install @inco/solana-sdkRust Crate(链上):
添加到你的:
Cargo.tomltoml
[dependencies]
inco-lightning = { version = "0.1", features = ["cpi"] }添加到:
Anchor.tomltoml
[programs.devnet]
inco_lightning = "5sjEbPiqgZrYwR31ahR6Uk9wf5awoX61YGg7jExQSwaj"JavaScript SDK(客户端):
bash
npm install @inco/solana-sdkBasic 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.
| Type | Description | Rust Definition |
|---|---|---|
| Encrypted unsigned 128-bit integer | |
| Encrypted boolean | |
Store handles directly in account structs:
rust
#[account]
pub struct ConfidentialAccount {
pub balance: Euint128,
pub is_active: Ebool,
}句柄是指向存储在协同验证节点网络链下的加密值的128位引用。
| 类型 | 描述 | Rust定义 |
|---|---|---|
| 加密的无符号128位整数 | |
| 加密的布尔值 | |
直接在账户结构体中存储句柄:
rust
#[account]
pub struct ConfidentialAccount {
pub balance: Euint128,
pub is_active: Ebool,
}Input Functions
输入函数
| Function | Description |
|---|---|
| Create from client-encrypted ciphertext |
| Create encrypted bool from ciphertext |
| Trivial encryption of plaintext u128 (for constants like zero) |
| Trivial encryption of plaintext bool |
| 函数 | 描述 |
|---|---|
| 从客户端加密的密文创建句柄 |
| 从密文创建加密布尔值 |
| 对明文u128进行简单加密(用于零等常量) |
| 对明文布尔值进行简单加密 |
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 () is for encrypted-encrypted operations, when the left operand is plaintext.
scalar_byte01所有运算都需要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_byte01Arithmetic → Euint128
Euint128算术运算 → Euint128
Euint128e_adde_sube_mule_reme_adde_sube_mule_remComparison → Ebool
Ebool比较运算 → Ebool
Eboole_gee_gte_lee_lte_eqe_gee_gte_lee_lte_eqBitwise → Euint128
Euint128位运算 → Euint128
Euint128e_ande_ore_note_shle_shre_ande_ore_note_shle_shrControl 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_accountsSee resources/access-control.md for the full simulation-then-submit pattern.
解密权限通过从派生的Allowance PDA进行管理。
[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)?;重要提示: 运算会生成新的句柄,而Allowance PDA依赖于句柄值。你必须先模拟交易以获取结果句柄,派生PDA,然后通过提交交易。
remaining_accounts完整的“先模拟再提交”模式请查看resources/access-control.md。
Attested Decryption
经认证的解密
Two modes:
| Mode | Purpose | Returns |
|---|---|---|
| Attested Reveal | Display values in UI | |
| Attested Decrypt | Verify values on-chain | |
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中显示值 | |
| 经认证的解密 | 在链上验证值 | |
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_mintcreate_accountmint_totransferapprovetypescript
// 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_mintcreate_accountmint_totransferapprovetypescript
// 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
最佳实践
- Always call after operations that produce handles you want to decrypt later
allow() - Use to pass allowance PDAs and grant access in the same transaction
remaining_accounts - Grant minimal permissions — only allow specific addresses to decrypt what they need
- Use the multiplexer pattern () instead of if/else on encrypted conditions
e_select - Trivial encryption only for constants (like zero) — use client-side encryption for sensitive values
- Verify the intended handle in attestations to prevent handle-swap attacks
- Simulate transactions first to get result handles before deriving allowance PDAs
- 在生成需后续解密的句柄的运算后,务必调用
allow() - 使用在同一交易中传递Allowance PDA并授予权限
remaining_accounts - 授予最小权限 — 仅允许特定地址解密所需内容
- 使用多路复用器模式 () 替代对加密条件使用if/else
e_select - 仅对常量使用简单加密(如零)—— 敏感值请使用客户端加密
- 在认证信息中验证目标句柄 以防止句柄替换攻击
- 先模拟交易 在派生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 helpersinco/
├── 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 # 包含工具函数的启动模板