> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inco.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Account Structs

> Understanding CPI account structures for Inco Lightning

# Account Structs

When making CPI calls to Inco Lightning, you need to pass specific account structures. This guide explains each account struct and when to use it.

## Overview

| Struct            | Purpose                        | Used By                                                              |
| ----------------- | ------------------------------ | -------------------------------------------------------------------- |
| `Operation`       | General encrypted operations   | All arithmetic, comparison, bitwise, random, input, select functions |
| `Allow`           | Grant/revoke decryption access | `allow` function                                                     |
| `IsAllowed`       | Check decryption permissions   | `is_allowed` function                                                |
| `VerifySignature` | Verify attestation signatures  | `is_validsignature` function                                         |

## Operation

The simplest account struct, used for most encrypted operations.

```rust theme={null}
use inco_lightning::cpi::accounts::Operation;

pub struct Operation<'info> {
    pub signer: AccountInfo<'info>,
}
```

**When to use**: Any encrypted computation - arithmetic (`e_add`, `e_sub`, `e_mul`, `e_rem`), comparisons (`e_ge`, `e_gt`, `e_le`, `e_lt`, `e_eq`), bitwise operations (`e_and`, `e_or`, `e_not`, `e_shl`, `e_shr`), random generation (`e_rand`), input functions (`new_euint128`, `new_ebool`, `as_euint128`, `as_ebool`), and conditional selection (`e_select`).

```rust theme={null}
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)?;
```

## Allow

Used to grant or revoke decryption permissions for a handle.

```rust theme={null}
use inco_lightning::cpi::accounts::Allow;

pub struct Allow<'info> {
    pub allowance_account: AccountInfo<'info>,
    pub signer: AccountInfo<'info>,
    pub allowed_address: AccountInfo<'info>,
    pub system_program: AccountInfo<'info>,
}
```

**When to use**: When you need to grant an address permission to decrypt a handle, or revoke previously granted permission.

| Account             | Description                                                  |
| ------------------- | ------------------------------------------------------------ |
| `allowance_account` | PDA that stores the allowance state (mutable)                |
| `signer`            | The handle owner who can grant permissions (mutable, signer) |
| `allowed_address`   | The address being granted/revoked access                     |
| `system_program`    | Required for PDA creation                                    |

### Allowance PDA Derivation

The allowance account is a PDA derived from the handle and allowed address:

```
seeds = [handle.to_le_bytes(), allowed_address]
```

**Client-side (TypeScript):**

```typescript theme={null}
import { PublicKey } from '@solana/web3.js';

const INCO_LIGHTNING_PROGRAM_ID = new PublicKey('5sjEbPiqgZrYwR31ahR6Uk9wf5awoX61YGg7jExQSwaj');

function findAllowanceAccount(handle: bigint, allowedAddress: PublicKey): PublicKey {
  const handleBuffer = Buffer.alloc(16);
  handleBuffer.writeBigUInt64LE(handle & BigInt('0xFFFFFFFFFFFFFFFF'), 0);
  handleBuffer.writeBigUInt64LE(handle >> BigInt(64), 8);

  const [allowanceAccount] = PublicKey.findProgramAddressSync(
    [handleBuffer, allowedAddress.toBuffer()],
    INCO_LIGHTNING_PROGRAM_ID
  );

  return allowanceAccount;
}
```

### Usage

```rust theme={null}
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.allowed_address.to_account_info(),
        system_program: ctx.accounts.system_program.to_account_info(),
    },
);

// Grant access
allow(cpi_ctx, handle, true, allowed_address)?;

// Or revoke access
allow(cpi_ctx, handle, false, allowed_address)?;
```

## IsAllowed

Used to check if an address has decryption permission.

```rust theme={null}
use inco_lightning::cpi::accounts::IsAllowed;

pub struct IsAllowed<'info> {
    pub allowance_account: AccountInfo<'info>,
    pub allowed_address: AccountInfo<'info>,
}
```

**When to use**: When you need to verify if an address can decrypt a handle before performing an action.

```rust theme={null}
let cpi_ctx = CpiContext::new(
    ctx.accounts.inco_lightning_program.to_account_info(),
    IsAllowed {
        allowance_account: ctx.accounts.allowance_account.to_account_info(),
        allowed_address: ctx.accounts.allowed_address.to_account_info(),
    },
);

let has_access = is_allowed(cpi_ctx, handle)?;
```

## VerifySignature

Used to verify Ed25519 signatures from the covalidator network for attested decryption.

```rust theme={null}
use inco_lightning::cpi::accounts::VerifySignature;

pub struct VerifySignature<'info> {
    pub instructions: AccountInfo<'info>,
    pub signer: AccountInfo<'info>,
}
```

**When to use**: When verifying that decrypted values came from the covalidator network (attested decryption).

| Account        | Description                                        |
| -------------- | -------------------------------------------------- |
| `instructions` | The instructions sysvar (`SYSVAR_INSTRUCTIONS_ID`) |
| `signer`       | Transaction signer (mutable, signer)               |

```rust theme={null}
use solana_program::sysvar::instructions::ID as SYSVAR_INSTRUCTIONS_ID;

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(),
    },
);

let results = is_validsignature(
    cpi_ctx,
    1,                      // expected signature count
    Some(handles),
    Some(plaintext_values),
)?;
```

## Setting Up Your Instruction

Your instruction's account struct needs to include the Inco Lightning program:

```rust theme={null}
use inco_lightning::ID as INCO_LIGHTNING_ID;

#[derive(Accounts)]
pub struct MyInstruction<'info> {
    #[account(mut)]
    pub authority: Signer<'info>,

    #[account(mut)]
    pub my_account: Account<'info, MyAccount>,

    /// CHECK: Inco Lightning program
    #[account(address = INCO_LIGHTNING_ID)]
    pub inco_lightning_program: AccountInfo<'info>,
}
```

For access control operations, include additional accounts:

```rust theme={null}
#[derive(Accounts)]
pub struct GrantAccess<'info> {
    #[account(mut)]
    pub authority: Signer<'info>,

    /// CHECK: Allowance PDA
    #[account(mut)]
    pub allowance_account: AccountInfo<'info>,

    /// CHECK: Address being granted access
    pub allowed_address: AccountInfo<'info>,

    /// CHECK: Inco Lightning program
    #[account(address = INCO_LIGHTNING_ID)]
    pub inco_lightning_program: AccountInfo<'info>,

    pub system_program: Program<'info, System>,
}
```

For signature verification, include the instructions sysvar:

```rust theme={null}
use solana_program::sysvar::instructions::ID as SYSVAR_INSTRUCTIONS_ID;

#[derive(Accounts)]
pub struct VerifyDecryption<'info> {
    #[account(mut)]
    pub authority: Signer<'info>,

    /// CHECK: Instructions sysvar
    #[account(address = SYSVAR_INSTRUCTIONS_ID)]
    pub instructions: AccountInfo<'info>,

    /// CHECK: Inco Lightning program
    #[account(address = INCO_LIGHTNING_ID)]
    pub inco_lightning_program: AccountInfo<'info>,
}
```
