mcpField
I
inco-svm

inco-svm

github.com/sendaifun開発13094 回インストール13 週間前に更新
リポジトリ

inco-svm について

inco-svmは、Inco LightningとTEEを使い、暗号化データを計算するSolanaアプリ開発者向けのスキルです。ベータ版で、暗号演算、復号権限管理、Confidential SPL Tokenを扱います。

主な機能

  1. 01暗号化された整数・真偽値ハンドル
  2. 02算術・比較・ビット演算
  3. 03ハンドル単位の復号権限
  4. 04TEEによる証明付き復号
  5. 05Confidential SPL Token機能
  6. 06Rust・JavaScript SDKの案内

活用シーン

  1. 01暗号化値を処理するSolanaプログラムの構築
  2. 02結果を復号できるアドレスの制御
  3. 03残高と送金を暗号化したトークンの作成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/sendaifun/skills --skill inco-svm

インストール後、Claude Code で/inco-svmを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

docs/
troubleshooting.md
examples/basic-operations/
encrypted-operations.ts
examples/confidential-spl-token/
mint-and-transfer.ts
reveal-balance.ts
examples/private-raffle/
raffle-client.ts
resources/
access-control.md
confidential-spl-token.md
js-sdk-reference.md
rust-sdk-reference.md
templates/
inco-svm-setup.ts

詳細

Inco SVM — Solana 上の機密コンピューティング

Inco Lightning は Solana 向けの機密性レイヤーです。開発者は、計算中も機密データを暗号化されたまま保てるアプリケーションを構築できます。Trusted Execution Environment(TEE)を使用して検証可能な機密コンピューティングを実現します。新しいチェーンも新しいウォレットも必要ありません。

注: Inco SVM は現在、Solana devnet 上で ベータ版 です。機能は変更される場合があります。

概要

  • 暗号化型 — オフチェーンに保存された暗号化値を表す Euint128 と Ebool のハンドル
  • 準同型演算 — CPI を介して暗号化データに対する算術演算、比較、ビット演算、制御フローを実行
  • アクセス制御 — ハンドルごとの復号権限を付与する Allowance PDA システム
  • アテステーション付き復号 — TEE 共検証者を介した Ed25519 署名検証済みの復号
  • 機密 SPL トークン — 残高と送金を暗号化する、プライバシーを保護するトークン規格
  • クライアント SDK — 暗号化、復号、ユーティリティーヘルパーを提供する @inco/solana-sdk

アーキテクチャ

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

クイックスタート

インストール

Rust クレート(オンチェーン):

Cargo.toml に追加します:

[dependencies]
inco-lightning = { version = "0.1", features = ["cpi"] }

Anchor.toml に追加します:

[programs.devnet]
inco_lightning = "5sjEbPiqgZrYwR31ahR6Uk9wf5awoX61YGg7jExQSwaj"

JavaScript SDK(クライアント側):

npm install @inco/solana-sdk
基本的なプログラムのセットアップ
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,
}
基本的なクライアントの使用方法
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]);

暗号化型とハンドル

ハンドルは、共検証者ネットワークのオフチェーンに保存された暗号化値への 128 ビット参照です。

型説明Rust の定義
Euint128暗号化された符号なし 128 ビット整数pub struct Euint128(pub u128)
Ebool暗号化されたブール値pub struct Ebool(pub u128)

ハンドルはアカウント構造体に直接保存します:

#[account]
pub struct ConfidentialAccount {
    pub balance: Euint128,
    pub is_active: Ebool,
}
入力関数
関数説明
new_euint128(ctx, ciphertext, input_type)クライアント側で暗号化された暗号文から作成します
new_ebool(ctx, ciphertext, input_type)暗号文から暗号化されたブール値を作成します
as_euint128(ctx, value)平文の u128 を簡易的に暗号化します(ゼロなどの定数用)
as_ebool(ctx, value)平文のブール値を簡易的に暗号化します

暗号化データに対する演算

すべての演算には CPI コンテキストが必要で、新しいハンドルを返します。

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 です。

算術演算 → Euint128

e_add、e_sub、e_mul、e_rem

比較 → Ebool

e_ge、e_gt、e_le、e_lt、e_eq

ビット演算 → Euint128

e_and、e_or、e_not、e_shl、e_shr

制御フロー(マルチプレクサ)
// Cannot use if/else on encrypted values — use e_select instead
let result = e_select(cpi_ctx, condition, if_true, if_false, 0)?;
乱数生成
let random_value = e_rand(cpi_ctx, 0)?;

完全な API については、resources/rust-sdk-reference.md を参照してください。

アクセス制御

復号権限は、[handle.to_le_bytes(), allowed_address] から導出される Allowance PDA で管理します。

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 を参照してください。

アテステーション付き復号

2 つのモードがあります:

モード目的戻り値
アテステーション付き公開UI に値を表示するresult.plaintexts
アテステーション付き復号オンチェーンで値を検証するresult.ed25519Instructions + program IX
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);

オンチェーン検証:

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))?;

機密 SPL トークン

プライバシーを保護するトークンの完全な実装です。resources/confidential-spl-token.md を参照してください。

主な関数:initialize_mint、create_account、mint_to、transfer、approve

// 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();

ベストプラクティス

  1. 後で復号するハンドルを生成する操作の後は、必ず allow() を呼び出してください
  2. remaining_accounts を使用して許可 PDA を渡し、同じトランザクション内でアクセスを許可してください
  3. 最小限の権限を付与してください — 必要なものを復号できるよう、特定のアドレスにのみ許可してください
  4. 暗号化された条件に対する if/else の代わりに、マルチプレクサーパターン(e_select)を使用してください
  5. 暗号化するのは定数(ゼロなど)のみにしてください — 機密性の高い値にはクライアント側の暗号化を使用してください
  6. ハンドルのすり替え攻撃を防ぐため、アテステーションで意図したハンドルを確認してください
  7. トランザクションを先にシミュレートして、許可 PDA を導出する前に結果のハンドルを取得してください

リソース

スキルの構成

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

コメント