Skip to content

Latest commit

 

History

History
1090 lines (886 loc) · 31.1 KB

File metadata and controls

1090 lines (886 loc) · 31.1 KB

KẾ HOẠCH TRIỂN KHAI WALRUS & SEAL - DỰA TRÊN TÀI LIỆU CHÍNH THỨC

NGUYÊN TẮC CƠ BẢN

Điểm quan trọng về Walrus:

  • TẤT CẢ BLOB TRÊN WALRUS ĐỀU PUBLIC - có thể bị khám phá bởi tất cả mọi người
  • Walrus chỉ đảm bảo availability (tính sẵn có) và integrity (toàn vẹn) của dữ liệu
  • BẮT BUỘC phải mã hóa bằng Seal nếu lưu trữ dữ liệu bí mật/riêng tư
  • Walrus sử dụng erasure coding để phân mảnh và phân tán dữ liệu

Vai trò của Seal (Identity-Based Encryption):

  • IBE (Identity-Based Encryption) với threshold cryptography
  • Không bên nào giữ toàn bộ khóa giải mã - key servers phân tán giữ key shares
  • Access control onchain - mọi giải mã phải qua Move function seal_approve
  • Tích hợp tự nhiên với Walrus - encrypted data trên Walrus, access policy onchain

Identity trong Seal:

  • Identity = [packageId][inner_id]
  • packageId: namespace cho access control
  • inner_id: ID cụ thể (ví dụ: lora_id, timestamp cho time-lock)

KIẾN TRÚC TỔNG QUAN

┌──────────────────────────────────────────────────────────────────┐
│                    FRONTEND (Next.js)                             │
│  - Sui Wallet integration                                         │
│  - Seal SDK (@mysten/seal)                                        │
│  - SessionKey management                                          │
└────────┬──────────────────────────────────────┬──────────────────┘
         │                                      │
    ┌────▼─────────┐                      ┌────▼───────────┐
    │  SUI CHAIN   │                      │ WALRUS STORAGE │
    │              │                      │                │
    │ Move Smart   │◄────────────────────►│ Encrypted      │
    │ Contracts:   │  Verify onchain      │ Blobs          │
    │              │                      │                │
    │ - seal_      │                      │ (Public but    │
    │   approve()  │                      │  encrypted)    │
    │ - LoRA       │                      │                │
    │   Asset      │                      │                │
    │ - Rental     │                      │                │
    │   System     │                      │                │
    └──────┬───────┘                      └────────────────┘
           │                                       ▲
           │ Verify License                        │
           │                                       │ Fetch blob
    ┌──────▼────────┐         ┌──────────────────┘
    │ SEAL KEY      │         │
    │ SERVERS       │◄────────┤
    │ (Threshold    │  Request│
    │  2/3 quorum)  │  key    │
    └───────────────┘  share  │
           │                  │
           │ Return key share │
           │                  │
    ┌──────▼──────────────────▼──────┐
    │       AI BACKEND                │
    │  - Seal SDK                     │
    │  - SessionKey                   │
    │  - ComfyUI/Stable Diffusion     │
    │  - Inference Engine             │
    └─────────────────────────────────┘

LUỒNG HOẠT ĐỘNG CHI TIẾT

1. UPLOAD LORA (OWNER)

Step 1: Chuẩn bị Smart Contract

Mục đích: Deploy Move contract với seal_approve function

Công việc:

  1. Viết Move module với seal_approve function

    • Function signature: entry fun seal_approve(id: vector<u8>, ...other_params)
    • id: inner identity (không bao gồm packageId, Seal sẽ tự thêm)
    • Function phải side-effect free (không modify state trong logic approve)
    • Return void, nhưng assert!() nếu không cho phép
  2. Example seal_approve cho rental:

    entry fun seal_approve(
        id: vector<u8>,           // inner identity = bcs::to_bytes(lora_id)
        license: &RentalLicense,   // reference to license object
        clock: &Clock             // Sui Clock object
    ) {
        // Parse inner id to get lora_id
        let mut bcs_id = bcs::new(id);
        let lora_id_from_id = bcs_id.peel_address();
    
        // Verify license matches lora
        assert!(license.lora_id == lora_id_from_id, EInvalidLoRA);
    
        // Verify license not expired
        assert!(license.end_time > clock.timestamp_ms(), EExpiredLicense);
    
        // Verify license active
        assert!(license.is_active == true, EInactiveLicense);
    }
  3. Deploy contract lên Sui:

    • sui client publish
    • Lưu lại packageId
  4. Tạo LoRAAsset object:

    public fun create_lora(
        name: String,
        description: String,
        ctx: &mut TxContext
    ): LoRAAsset {
        LoRAAsset {
            id: object::new(ctx),
            name,
            description,
            owner: tx_context::sender(ctx),
            walrus_blob_id: option::none(), // Sẽ update sau
            is_active: true
        }
    }

Step 2: Mã hóa bằng Seal SDK (Frontend)

Mục đích: Encrypt LoRA file trước khi upload

Công việc:

  1. Setup SealClient:

    import { SealClient, getAllowlistedKeyServers } from '@mysten/seal';
    import { SuiClient, getFullnodeUrl } from '@mysten/sui.js/client';
    
    const suiClient = new SuiClient({ url: getFullnodeUrl('testnet') });
    
    // Get verified key servers cho testnet
    const serverObjectIds = getAllowlistedKeyServers('testnet');
    
    const sealClient = new SealClient({
        suiClient,
        serverConfigs: serverObjectIds.map(id => ({
            objectId: id,
            weight: 1,  // Equal weight cho mỗi server
        })),
        verifyKeyServers: false, // Set true cho production
    });
  2. Read file và encrypt:

    // Read LoRA file
    const fileBuffer = await file.arrayBuffer();
    const fileBytes = new Uint8Array(fileBuffer);
    
    // Prepare inner identity = lora_id
    const loraIdBytes = fromHEX(loraAsset.id); // Convert lora ID to bytes
    
    // Encrypt
    const { encryptedObject, key } = await sealClient.encrypt({
        threshold: 2,           // Cần 2/3 key servers để decrypt
        packageId: PACKAGE_ID,  // Package ID từ step 1.3
        id: loraIdBytes,        // Inner identity = lora_id
        data: fileBytes,        // LoRA file content
    });
    
    // Optional: Backup symmetric key an toàn
    // key có thể dùng để decrypt thủ công nếu cần
    securelyStoreKey(loraAsset.id, key);
  3. Parse encrypted object (optional, để debug):

    import { EncryptedObject } from '@mysten/seal';
    
    const parsed = EncryptedObject.parse(encryptedObject);
    console.log('Encrypted with ID:', parsed.id);

Step 3: Upload lên Walrus

Mục đích: Store encrypted data lên Walrus

Công việc:

  1. Upload qua Walrus CLI:

    # Save encryptedObject to file first (in your upload handler)
    echo "<encryptedObject_hex>" | xxd -r -p > lora_encrypted.bin
    
    # Upload to Walrus
    walrus store lora_encrypted.bin --epochs 100
    
    # Output: blob_id
  2. Hoặc upload qua HTTP API:

    const response = await fetch('https://publisher.walrus-testnet.walrus.space/v1/store', {
        method: 'PUT',
        headers: {
            'Content-Type': 'application/octet-stream',
        },
        body: encryptedObject,
    });
    
    const result = await response.json();
    const blobId = result.newlyCreated.blobObject.blobId;
  3. Update LoRAAsset trên Sui:

    const tx = new Transaction();
    tx.moveCall({
        target: `${PACKAGE_ID}::lora_asset::update_blob_id`,
        arguments: [
            tx.object(loraAssetId),
            tx.pure.string(blobId),
        ],
    });
    
    await signAndExecute(tx);
  4. Tạo RentalPolicy:

    const tx = new Transaction();
    tx.moveCall({
        target: `${PACKAGE_ID}::rental_system::create_rental_policy`,
        arguments: [
            tx.object(loraAssetId),
            tx.pure.u64(pricePerDay),
            tx.pure.u64(minDuration),
            tx.pure.u64(maxDuration),
        ],
    });
    
    await signAndExecute(tx);

Kết quả:

  • ✅ LoRA được mã hóa bằng Seal (threshold encryption)
  • ✅ Encrypted blob lưu trên Walrus (public nhưng không decrypt được)
  • ✅ LoRAAsset onchain chứa blob_id
  • ✅ RentalPolicy ready cho thuê

2. THUÊ LORA (RENTER)

Step 1: Browse Marketplace

Công việc:

  1. Query LoRAAsset objects từ Sui
  2. Hiển thị danh sách với metadata
  3. User chọn LoRA và click "Rent"

Step 2: Thuê và Mint License

Công việc:

  1. Tạo transaction thuê:

    const tx = new Transaction();
    
    // Transfer payment
    const [coin] = tx.splitCoins(tx.gas, [pricePerDay * duration]);
    
    // Call rent function
    tx.moveCall({
        target: `${PACKAGE_ID}::rental_system::rent_lora`,
        arguments: [
            tx.object(MARKETPLACE_ID),
            tx.object(loraId),
            tx.pure.u64(duration),
            coin,
        ],
    });
    
    await wallet.signAndExecuteTransaction({ transaction: tx });
  2. Smart contract tạo RentalLicense:

    public fun rent_lora(
        marketplace: &mut RentalMarketplace,
        lora_id: ID,
        duration: u64,
        payment: Coin<SUI>,
        clock: &Clock,
        ctx: &mut TxContext
    ) {
        // Verify payment
        let policy = get_rental_policy(marketplace, lora_id);
        assert!(coin::value(&payment) >= policy.price_per_day * duration, EInsufficientPayment);
    
        // Create license
        let license = RentalLicense {
            id: object::new(ctx),
            lora_id,
            renter: tx_context::sender(ctx),
            start_time: clock.timestamp_ms(),
            end_time: clock.timestamp_ms() + (duration * 86400000), // days to ms
            is_active: true,
            usage_count: 0,
        };
    
        // Transfer license to renter
        transfer::transfer(license, tx_context::sender(ctx));
    
        // Process payment
        process_payment(marketplace, payment);
    
        // Emit event
        event::emit(LoRARented { lora_id, renter: tx_context::sender(ctx), duration });
    }

Kết quả:

  • ✅ RentalLicense NFT trong wallet của renter
  • ✅ License recorded onchain với end_time
  • ✅ Payment processed

3. SỬ DỤNG LORA - INFERENCE (RENTER)

Step 1: Gửi Request (Frontend)

Công việc:

  1. User chọn LoRA đã thuê
  2. Nhập prompt
  3. Gửi request tới Backend với wallet signature

Step 2: Verify License (Backend)

Công việc:

def verify_license(user_address, lora_id):
    # Query Sui cho license
    licenses = sui_client.get_owned_objects(
        user_address,
        filter={"StructType": f"{PACKAGE_ID}::rental_system::RentalLicense"}
    )

    # Find license for this LoRA
    for license in licenses:
        if license.lora_id == lora_id and license.is_active:
            if license.end_time > current_timestamp_ms():
                return license

    raise Unauthorized("No valid license found")

Step 3: Tạo SessionKey (Backend)

Mục đích: SessionKey cần cho decrypt

Công việc:

import { SessionKey } from '@mysten/seal';

// Create SessionKey
const sessionKey = await SessionKey.create({
    address: userAddress,      // Renter's address
    packageId: PACKAGE_ID,
    ttlMin: 60,               // Session valid for 60 minutes
    suiClient,
});

// Get personal message to sign
const personalMessage = sessionKey.getPersonalMessage();

// User signs message (in practice, cached or signed earlier)
// For backend: có thể dùng Signer directly
const signer = await getBackendSigner();
await sessionKey.setPersonalMessageSignature(
    await signer.signPersonalMessage(personalMessage)
);

// sessionKey is now initialized

Lưu ý về SessionKey:

  • SessionKey cần user signature để initialize
  • TTL (time-to-live) giới hạn thời gian sử dụng
  • Có thể cache trong IndexedDB (frontend) hoặc memory (backend)
  • Optional: có thể pass mvr_name (Move Package Registry name) để improve UX

Step 4: Build Transaction cho seal_approve

Mục đích: Tạo proof onchain để Seal verify

Công việc:

const tx = new Transaction();

// Prepare inner identity = lora_id
const loraIdBytes = fromHEX(loraId);

tx.moveCall({
    target: `${PACKAGE_ID}::seal_integration::seal_approve`,
    arguments: [
        tx.pure.vector("u8", loraIdBytes),  // inner id
        tx.object(licenseId),                // license object
        tx.object('0x6'),                    // Clock object (always 0x6)
    ],
});

// Build transaction (ONLY transactionKind, không cần sign)
const txBytes = await tx.build({
    client: suiClient,
    onlyTransactionKind: true,  // ⭐ QUAN TRỌNG
});

// txBytes này sẽ dùng cho decrypt

Lưu ý quan trọng:

  • KHÔNG execute transaction này
  • Chỉ cần txBytes (transactionKind)
  • Seal SDK sẽ dùng txBytes để verify onchain
  • Transaction phải valid (seal_approve không throw error)

Step 5: Fetch Encrypted Blob từ Walrus

Công việc:

import requests

# Get blob_id from LoRAAsset
lora_asset = sui_client.get_object(lora_id)
blob_id = lora_asset.data.walrus_blob_id

# Fetch from Walrus aggregator
response = requests.get(f'https://aggregator.walrus-testnet.walrus.space/v1/{blob_id}')

if response.status_code == 200:
    encrypted_bytes = response.content
else:
    raise Exception(f'Failed to fetch blob: {response.status_code}')

Step 6: Decrypt bằng Seal SDK

Mục đích: Giải mã để lấy LoRA weights

Công việc:

// Decrypt
const decryptedBytes = await sealClient.decrypt({
    data: encryptedBytes,     // From Walrus
    sessionKey: sessionKey,   // Initialized SessionKey
    txBytes: txBytes,         // Transaction kind from step 4
});

// decryptedBytes is now the original LoRA .safetensors file

Seal thực hiện internally:

  1. Verify txBytes onchain (simulate transaction)
  2. Nếu seal_approve pass → request key shares từ key servers
  3. Key servers verify:
    • Transaction valid?
    • Signature match?
    • Policy allow?
  4. Each key server return key share
  5. Tổng hợp key shares (threshold: 2/3)
  6. Decrypt data với reconstructed key
  7. Return plaintext

Lưu ý:

  • Nếu seal_approve fail → decrypt fail
  • Nếu không đủ key servers respond → decrypt fail
  • Key servers có rate limiting → design app carefully
  • Cache keys internally trong SealClient (reuse client instance)

Step 7: Load LoRA và Inference

Công việc:

import safetensors

# Load LoRA vào memory (không save file)
lora_tensors = safetensors.torch.load(io.BytesIO(decrypted_bytes))

# Load vào ComfyUI/Stable Diffusion
model.load_lora(lora_tensors)

# Run inference
image = model.generate(prompt, settings)

# Apply watermark
watermarked_image = apply_watermark(image, license_id)

# Cleanup
del lora_tensors
del decrypted_bytes

return watermarked_image

Step 8: Update Usage

Công việc:

const tx = new Transaction();
tx.moveCall({
    target: `${PACKAGE_ID}::rental_system::increment_usage`,
    arguments: [
        tx.object(licenseId),
    ],
});

await signAndExecute(tx);

Kết quả:

  • ✅ Image generated với LoRA
  • ✅ LoRA weights không leak (memory-only)
  • ✅ Usage tracked onchain
  • ✅ Audit trail immutable

4. HẾT HẠN LICENSE

Step 1: Monitor & Revoke

Công việc:

// Cronjob chạy định kỳ
async function revokeExpiredLicenses() {
    // Query all active licenses
    const licenses = await sui_client.queryEvents({
        query: { MoveEventType: `${PACKAGE_ID}::rental_system::LoRARented` }
    });

    for (const license of licenses) {
        if (license.end_time < Date.now()) {
            // Revoke
            const tx = new Transaction();
            tx.moveCall({
                target: `${PACKAGE_ID}::rental_system::revoke_license`,
                arguments: [tx.object(license.id)],
            });
            await signAndExecute(tx);
        }
    }
}

Step 2: Automatic Enforcement

Cơ chế:

  • Lần inference tiếp theo, seal_approve sẽ check:
    assert!(license.end_time > clock.timestamp_ms(), EExpiredLicense);
  • Nếu expired → assert fail → transaction fail → decrypt fail
  • Backend return error: "License expired"

Kết quả:

  • ✅ Auto-enforcement qua seal_approve
  • ✅ Không cần manual revocation (nhưng nên có cho consistency)
  • ✅ Onchain audit trail

CÁC THÀNH PHẦN SMART CONTRACT

Module 1: lora_asset.move

struct LoRAAsset has key, store {
    id: UID,
    name: String,
    description: String,
    owner: address,
    walrus_blob_id: Option<String>,
    is_active: bool,
}

public fun create_lora(...): LoRAAsset { ... }
public fun update_blob_id(asset: &mut LoRAAsset, blob_id: String) { ... }
public fun deactivate(asset: &mut LoRAAsset) { ... }

Module 2: rental_system.move

struct RentalPolicy has key, store {
    id: UID,
    lora_id: ID,
    price_per_day: u64,
    min_duration: u64,
    max_duration: u64,
}

struct RentalLicense has key, store {
    id: UID,
    lora_id: ID,
    renter: address,
    start_time: u64,
    end_time: u64,
    is_active: bool,
    usage_count: u64,
}

public fun create_rental_policy(...) { ... }
public fun rent_lora(...): RentalLicense { ... }
public fun revoke_license(license: &mut RentalLicense) { ... }
public fun increment_usage(license: &mut RentalLicense) { ... }

Module 3: seal_integration.move ⭐ QUAN TRỌNG

const EInvalidLoRA: u64 = 1;
const EExpiredLicense: u64 = 2;
const EInactiveLicense: u64 = 3;

/// Seal approval function
/// Identity structure: [packageId][inner_id]
/// inner_id = bcs::to_bytes(lora_id)
entry fun seal_approve(
    id: vector<u8>,              // Inner identity only
    license: &RentalLicense,     // Reference to license
    clock: &Clock                // Sui Clock (0x6)
) {
    // Parse inner id to get lora_id
    let mut bcs_id = bcs::new(id);
    let lora_id_from_id = bcs_id.peel_address();
    let remaining = bcs_id.into_remainder_bytes();

    // Verify entire id consumed
    assert!(remaining.length() == 0, EInvalidLoRA);

    // Verify license matches LoRA
    assert!(license.lora_id == lora_id_from_id, EInvalidLoRA);

    // Verify license not expired
    assert!(license.end_time > clock.timestamp_ms(), EExpiredLicense);

    // Verify license active
    assert!(license.is_active, EInactiveLicense);

    // If all checks pass, function returns normally
    // If any check fails, assert! will abort transaction
}

Lưu ý về seal_approve:

  • Function phải là entry fun
  • Phải side-effect free (không modify state trong approval logic)
  • Có thể read objects qua reference (&Object)
  • Dùng assert!() để reject access
  • Seal sẽ simulate transaction để verify

SEAL SDK APIS CHI TIẾT

SealClient

class SealClient {
    constructor(config: {
        suiClient: SuiClient;
        serverConfigs: Array<{
            objectId: string;      // Key server object ID
            weight: number;        // Weight for selection
            apiKeyName?: string;   // For authenticated servers
            apiKey?: string;
        }>;
        verifyKeyServers?: boolean;  // Verify URLs against onchain data
    });

    // Encrypt data
    async encrypt(options: {
        threshold: number;         // Min key servers needed (e.g., 2 for 2/3)
        packageId: string;         // Package containing seal_approve
        id: Uint8Array;           // Inner identity (not including packageId)
        data: Uint8Array;         // Data to encrypt
    }): Promise<{
        encryptedObject: Uint8Array;
        key: Uint8Array;          // Symmetric key (for backup)
    }>;

    // Decrypt data
    async decrypt(options: {
        data: Uint8Array;          // Encrypted data
        sessionKey: SessionKey;    // Initialized SessionKey
        txBytes: Uint8Array;       // Transaction bytes (onlyTransactionKind)
    }): Promise<Uint8Array>;

    // Fetch multiple keys efficiently
    async fetchKeys(options: {
        ids: string[];             // Multiple identity IDs
        txBytes: Uint8Array;       // Transaction with multiple seal_approve calls
        sessionKey: SessionKey;
        threshold: number;
    }): Promise<Map<string, Key>>;
}

SessionKey

class SessionKey {
    // Create new session key
    static async create(options: {
        address: string;           // Sui address
        packageId: string;         // Package ID
        ttlMin: number;           // Time-to-live in minutes
        suiClient: SuiClient;
        mvr_name?: string;        // Optional: package name for better UX
    }): Promise<SessionKey>;

    // Get message to sign
    getPersonalMessage(): Uint8Array;

    // Initialize with signature
    setPersonalMessageSignature(signature: Signature): void;

    // Persistence
    static async import(data: Uint8Array): Promise<SessionKey>;
    export(): Uint8Array;
}

Helper Functions

// Get allowlisted key servers
function getAllowlistedKeyServers(network: 'testnet' | 'mainnet'): string[];

// Parse encrypted object
class EncryptedObject {
    static parse(bytes: Uint8Array): {
        id: string;
        // ... other metadata
    };
}

KEY SERVER CONFIGURATION

Open Mode vs Permissioned Mode

Open Mode:

  • Shared master key cho tất cả clients
  • Public access, không cần authentication
  • Dùng cho development/testing
  • Rate limiting theo source IP

Permissioned Mode:

  • Mỗi client có dedicated master key
  • Cần API key authentication
  • Dùng cho production
  • Custom rate limits per client

Testnet Key Servers

Mysten Labs (Open):

  • mysten-testnet-1: https://seal-key-server-testnet-1.mystenlabs.com
  • mysten-testnet-2: https://seal-key-server-testnet-2.mystenlabs.com

Ruby Nodes:

  • Open: https://free-eu-central-1.api.rubynodes.io
    • Object ID: 0x781389fae54633649d78b731b708c5b363cf7fa4753a48997d4f6f82d5cc5b98
  • Permissioned: https://starter-eu-central-1.api.rubynodes.io

NodeInfra:

  • Open: https://open-seal-testnet.nodeinfra.com
    • Object ID: 0x5466b7df5c15b508678d51496ada8afab0d6f70a01c10613123382b1b8131007
  • Permissioned: https://seal-testnet.nodeinfra.com

Recommendation:

  • Development: Dùng Open mode với 3 key servers, threshold = 2
  • Production: Setup Permissioned mode với providers, threshold = 2/3

WALRUS APIS CHI TIẾT

Upload via CLI

# Store file
walrus store <file_path> --epochs <number>

# Output
Stored blob with ID: <blob_id>

Upload via HTTP API

curl -X PUT \
  https://publisher.walrus-testnet.walrus.space/v1/store \
  -H "Content-Type: application/octet-stream" \
  --data-binary @<file_path>

Response:

{
  "newlyCreated": {
    "blobObject": {
      "id": "0x...",
      "blobId": "<blob_id>",
      "size": 123456,
      ...
    }
  }
}

Download via HTTP API

curl https://aggregator.walrus-testnet.walrus.space/v1/<blob_id>

SECURITY BEST PRACTICES

1. Threshold Configuration

  • Recommended: threshold = 2, total servers = 3 (2/3 quorum)
  • Cao hơn → more secure nhưng higher latency
  • Thấp hơn → faster nhưng less resilient

2. SessionKey Management

  • TTL không quá dài (60 minutes recommended)
  • Rotate sessions định kỳ
  • Store securely (IndexedDB frontend, memory backend)
  • Clear sau khi dùng xong

3. seal_approve Security

  • CRITICAL: Validate ALL inputs
  • Check timestamp để prevent old transactions
  • Side-effect free (không modify state)
  • Test edge cases thoroughly

4. Backend Security

  • Verify wallet signatures
  • Rate limiting per user
  • Memory-only LoRA loading
  • Clear sensitive data sau inference
  • Monitor suspicious patterns

5. Key Backup

  • Symmetric key từ encrypt() có thể backup
  • Encrypt backup key với user's master key
  • Store trong secure storage
  • Có recovery flow nếu key servers down

RỦI RO VÀ GIẢM THIỂU

Key Server Unavailability

Rủi ro: Không đủ key servers respond Giảm thiểu:

  • Dùng 3+ key servers với threshold 2/3
  • Monitor key server health
  • Fallback to backup key nếu available
  • Alert team nếu servers down

seal_approve Bugs

Rủi ro: Logic bug cho phép unauthorized access Giảm thiểu:

  • Comprehensive testing
  • Audit code trước deploy
  • Test với expired/revoked licenses
  • Monitor failed decrypt attempts

Transaction Simulation Failures

Rủi ro: Recently created objects không query được Giảm thiểu:

  • Retry với exponential backoff
  • Wait 1-2 seconds sau object creation
  • Handle InvalidParameter errors gracefully

Rate Limiting

Rủi ro: Key servers rate limit requests Giảm thiểu:

  • Cache decrypted keys (reuse SealClient instance)
  • Batch decrypt multiple items
  • Use fetchKeys() cho multiple IDs
  • Design app để minimize key requests

SO SÁNH: SAI vs ĐÚNG

❌ Hiểu sai trước đây:

  1. Client-side AES encryption → SAI

    • Không dùng Seal threshold encryption
    • Backend giữ keys → security risk
  2. Tự tạo SealPolicy struct → SAI

    • Không có SealPolicy struct trong Seal
    • Access control qua seal_approve function
  3. Backend tự decrypt → SAI

    • Không có key servers involvement
    • Không có threshold security
  4. Direct decryption → SAI

    • Không verify onchain
    • Không có audit trail

✅ Cách đúng:

  1. Seal SDK encryption

    • Dùng SealClient.encrypt()
    • Threshold encryption với key servers
    • Identity-based encryption
  2. Move function seal_approve

    • Access control logic onchain
    • Side-effect free verification
    • Customizable policies
  3. SessionKey + Transaction

    • SessionKey cần user signature
    • Transaction proves onchain access
    • Key servers verify transaction
  4. Seal SDK decryption

    • SealClient.decrypt() với txBytes
    • Key servers return shares
    • Threshold reconstruction
    • Automatic verification

CHECKLIST TRIỂN KHAI

Phase 1: Smart Contracts

  • Viết lora_asset.move với LoRAAsset struct
  • Viết rental_system.move với RentalLicense
  • Viết seal_integration.move với seal_approve
  • Test seal_approve với:
    • Valid license
    • Expired license
    • Wrong LoRA
    • Inactive license
  • Deploy lên Sui testnet
  • Lưu packageId

Phase 2: Frontend Integration

  • Install @mysten/seal@mysten/sui.js
  • Setup SealClient với testnet key servers
  • Implement upload flow:
    • Read file
    • Encrypt với SealClient
    • Upload encryptedObject lên Walrus
    • Update Sui với blob_id
  • Test end-to-end upload

Phase 3: Backend Integration

  • Install Seal SDK (TypeScript/Python)
  • Implement license verification
  • Implement SessionKey creation
  • Implement seal_approve transaction building
  • Implement decrypt flow:
    • Fetch from Walrus
    • Decrypt với SealClient
    • Load LoRA
    • Run inference
  • Test full inference flow

Phase 4: Testing

  • Test expired license → decrypt fail
  • Test revoked license → decrypt fail
  • Test no license → decrypt fail
  • Test wrong user → decrypt fail
  • Test concurrent requests
  • Load testing với key servers
  • Measure latency

Phase 5: Production

  • Audit seal_approve logic
  • Setup Permissioned key servers
  • Configure rate limits
  • Setup monitoring:
    • Key server health
    • Decrypt success rate
    • Latency metrics
  • Deploy to mainnet
  • Setup alerts

PERFORMANCE OPTIMIZATION

1. SealClient Reuse

// ❌ BAD: Create new client per request
const client = new SealClient(...);
await client.decrypt(...);

// ✅ GOOD: Reuse client instance
const globalClient = new SealClient(...);
// Cache keys automatically
await globalClient.decrypt(...);
await globalClient.decrypt(...); // Faster if same ID

2. Batch Decryption

// Multiple seal_approve calls trong 1 transaction
const tx = new Transaction();

for (const loraId of loraIds) {
    tx.moveCall({
        target: `${PACKAGE_ID}::seal_integration::seal_approve`,
        arguments: [
            tx.pure.vector("u8", fromHEX(loraId)),
            tx.object(licenses[loraId]),
            tx.object('0x6'),
        ],
    });
}

const txBytes = await tx.build({ client, onlyTransactionKind: true });

// Fetch all keys at once
const keys = await sealClient.fetchKeys({
    ids: loraIds,
    txBytes,
    sessionKey,
    threshold: 2,
});

3. Symmetric Key Backup

// Store symmetric key an toàn
const { encryptedObject, key } = await sealClient.encrypt(...);

// Encrypt symmetric key với user's master key
const encryptedKey = await encryptWithUserKey(key, userMasterKey);
await secureStorage.save(loraId, encryptedKey);

// Decrypt directly với symmetric key (không cần key servers)
const decrypted = await symmetricDecrypt(encryptedObject, key);

TÀI LIỆU THAM KHẢO


KẾT LUẬN

Những điểm khác biệt chính:

  1. Encryption:

    • ❌ AES tự implement
    • ✅ Seal SDK với IBE + threshold
  2. Access Control:

    • ❌ Tự quản lý SealPolicy struct
    • ✅ Move function seal_approve onchain
  3. Decryption:

    • ❌ Backend giữ keys và decrypt trực tiếp
    • ✅ SessionKey + Transaction + Key servers
  4. Security:

    • ❌ Single point of failure (backend)
    • ✅ Threshold (2/3 key servers)

Lợi ích:

Threshold Security: Không bên nào giữ toàn bộ khóa ✅ Onchain Verification: Mọi access đều có proof ✅ Audit Trail: Immutable transaction history ✅ Flexible Policies: Custom logic trong seal_approve ✅ Decentralized: Key servers phân tán

Next Steps:

  1. Deploy smart contracts với seal_approve
  2. Setup Seal SDK integration (frontend + backend)
  3. Test với Walrus testnet + Seal testnet key servers
  4. Optimize performance (caching, batching)
  5. Audit security trước production
  6. Monitor và iterate

Updated: 2025-10-10 Version: 2.0 - Based on Official Seal & Walrus Documentation