Documentation Index
Fetch the complete documentation index at: https://docs.magicblock.gg/llms.txt
Use this file to discover all available pages before exploring further.
Permission Program
オンチェーン権限管理(近日公開)
Ephemeral Rollups SDK
Private Ephemeral Rollups 向け SDK
概要
Private Ephemeral Rollups は、コンプライアンスを中核に据えた Trusted Execution Environment 上で、permissioned accounts に対するきめ細かな権限制御を可能にする Ephemeral Rollups です。各 permission account は、メンバー一覧と、それぞれが実行できる操作を決める特定のフラグを保持します。基本概念
- Permission Account: 特定のアカウントに対するアクセス制御ルールを保存する PDA
- Members: フラグを通じて特定の権限を付与されたアドレス
- Flags: メンバーが何をできるか(authority、ログ閲覧、残高閲覧など)を定義するビットマスク
- Public Permissions: メンバーが
Noneに設定されると、permissioned account は一時的に可視状態になる
メンバーフラグ
メンバーフラグは、各メンバーに対するきめ細かな権限を定義します。フラグはビット OR で組み合わせることで、複数の権限を付与できます。 フラグの説明:- AUTHORITY: 権限設定の更新・委任、他メンバーの追加・削除、メンバーフラグの更新を許可します。
- TX_LOGS: トランザクション実行ログの閲覧を許可します。
- TX_BALANCES: アカウント残高の変化の閲覧を許可します。
- TX_MESSAGE: トランザクションメッセージデータの閲覧を許可します。
- ACCOUNT_SIGNATURES: アカウント署名の閲覧を許可します
- Rust SDK
- Pinocchio
- Web3.js
- Kit
use ephemeral_rollups_sdk::access_control::structs::{
Member,
AUTHORITY_FLAG,
TX_LOGS_FLAG,
TX_BALANCES_FLAG,
TX_MESSAGE_FLAG,
ACCOUNT_SIGNATURES_FLAG,
};
// Set flags by combining them with bitwise OR
let flags = AUTHORITY_FLAG | TX_LOGS_FLAG;
// Create a member with combined flags
let mut member = Member {
flags,
pubkey: user_pubkey,
};
// Check if member has a specific flag using bitwise AND
let is_authority = (member.flags & AUTHORITY_FLAG) != 0;
let can_see_logs = (member.flags & TX_LOGS_FLAG) != 0;
// Use helper methods to set/remove flags
member.set_flags(TX_BALANCES_FLAG); // Add a flag
member.remove_flags(TX_LOGS_FLAG); // Remove a flag
use ephemeral_rollups_pinocchio::types::{Member, MemberFlags};
use pinocchio::Address;
// Create and set flags using individual methods
let mut flags = MemberFlags::new();
flags.set(MemberFlags::AUTHORITY);
flags.set(MemberFlags::TX_LOGS);
flags.set(MemberFlags::TX_BALANCES);
// Create a member with flags
let member = Member {
flags,
pubkey: user_address,
};
// Remove a flag
flags.remove(MemberFlags::TX_LOGS);
// Create flags from individual boolean values
let flags = MemberFlags::from_acl_flags(
true, // authority
true, // tx_logs
false, // tx_balances
true, // tx_message
false, // account_signatures
);
// Convert flags to byte value
let flag_byte = flags.to_acl_flag_byte();
// Create flags from byte value
let flags = MemberFlags::from_acl_flag_byte(flag_byte);
import { PublicKey } from "@solana/web3.js";
import {
AUTHORITY_FLAG,
TX_LOGS_FLAG,
TX_BALANCES_FLAG,
TX_MESSAGE_FLAG,
ACCOUNT_SIGNATURES_FLAG,
type Member,
} from "@magicblock-labs/ephemeral-rollups-sdk";
// Set flags by combining them with bitwise OR
const flags = AUTHORITY_FLAG | TX_LOGS_FLAG;
// Create a member with combined flags
const member: Member = {
flags,
pubkey: new PublicKey(userAddress),
};
// Check if a flag is present using bitwise AND
const isAuthority = (member.flags & AUTHORITY_FLAG) !== 0;
const canSeeLogs = (member.flags & TX_LOGS_FLAG) !== 0;
const canSeeBalances = (member.flags & TX_BALANCES_FLAG) !== 0;
// Add a flag to existing flags
const updatedFlags = member.flags | TX_BALANCES_FLAG;
// Remove a flag from existing flags
const removedFlags = member.flags & ~TX_LOGS_FLAG;
import {
AUTHORITY_FLAG,
TX_LOGS_FLAG,
TX_BALANCES_FLAG,
TX_MESSAGE_FLAG,
ACCOUNT_SIGNATURES_FLAG,
isAuthority,
canSeeTxLogs,
canSeeTxBalances,
canSeeTxMessages,
canSeeAccountSignatures,
type Member,
} from "@magicblock-labs/ephemeral-rollups-sdk";
// Set flags by combining them with bitwise OR
const flags = AUTHORITY_FLAG | TX_LOGS_FLAG | TX_BALANCES_FLAG;
// Create a member with combined flags
const member: Member = {
flags,
pubkey: userAddress,
};
// Use helper functions to check specific permissions
const canModifyPermission = isAuthority(member, userAddress);
const canViewLogs = canSeeTxLogs(member, userAddress);
const canViewBalances = canSeeTxBalances(member, userAddress);
const canViewMessages = canSeeTxMessages(member, userAddress);
const canViewSignatures = canSeeAccountSignatures(member, userAddress);
// Add a flag to existing member
const updatedFlags = member.flags | TX_MESSAGE_FLAG;
// Remove a flag from existing member
const removedFlags = member.flags & ~TX_LOGS_FLAG;
Permission のライフサイクル
permissioned account の典型的なライフサイクルでは、MagicBlock の Permission ProgramACLseoPoyC3cBqoUtkbjZ4aDrkurZW86v19pXz2XQnp1 と Delegation Program DELeGGvXpWV2fqJUhqcF5ZSYMS4JTLjteaAMARRSaeSh との連携が必要です。
初期メンバーとそのフラグを持つ新しい permission account を初期化します。
Private Ephemeral Rollup に permission を委任し、強制力のあるリアルタイムアクセス制御を有効にします。
これらの公開バリデータは開発用として利用できます。委任命令には、 対象となる ER バリデータを必ず追加してください。
メインネット- アジア (as.magicblock.app):
MAS1Dt9qreoRMQ14YQuhg8UTZMMzDdKhmkZMECCzk57 - EU (eu.magicblock.app):
MEUGGrYPxKk17hCr7wpT6s8dtNokZj5U2L57vjYMS8e - 米国 (us.magicblock.app):
MUS3hc9TCw4cGC12vHNoYcCGzJG1txjgQLZWVoeNHNd - TEE (mainnet-tee.magicblock.app):
MTEWGuqxUpYZGFJQcp8tLN7x5v9BSeoFHYWQQ3n3xzo
- アジア (devnet-as.magicblock.app):
MAS1Dt9qreoRMQ14YQuhg8UTZMMzDdKhmkZMECCzk57 - EU (devnet-eu.magicblock.app):
MEUGGrYPxKk17hCr7wpT6s8dtNokZj5U2L57vjYMS8e - 米国 (devnet-us.magicblock.app):
MUS3hc9TCw4cGC12vHNoYcCGzJG1txjgQLZWVoeNHNd - TEE (devnet-tee.magicblock.app):
MTEWGuqxUpYZGFJQcp8tLN7x5v9BSeoFHYWQQ3n3xzo
- ローカル ER (localhost:7799):
mAGicPQYBMvcYveUZA5F5UNNwyHvfYh5xkLS2Fr1mev
必要に応じてメンバー権限を追加、削除、変更します。更新は Private Ephemeral Rollup 上でリアルタイムに行えます。
リクエストを行う前に、TEE RPC の完全性を検証し、認可トークンを取得します。適切なフラグを持つメンバーのみがアカウント状態へアクセスまたは変更できます。
最終状態を Solana に同期し、アカウントを Base Layer の制御に戻します。
不要になった permission account を閉じて lamports を回収します。
Permission 操作
- 1. 作成
- 2. 委任
- 3. 更新
- 4. リクエスト
- 5. コミットと委任解除
- 6. 閉じる
プログラムを作成したら、permission と delegation のフックを追加してアカウントへのアクセスを制御できます。例としてはクイックスタートを参照してください。MagicBlock の Permission Program ユースケース:
ACLseoPoyC3cBqoUtkbjZ4aDrkurZW86v19pXz2XQnp1 を通じて、初期メンバーとそのフラグを持つ新しい permission account を作成します。- Rust SDK
- Pinocchio
- Kit
- Web3.js
use ephemeral_rollups_sdk::access_control::{
instructions::CreatePermissionCpiBuilder,
structs::{
Member,
MembersArgs,
AUTHORITY_FLAG, // Member can directly modify the permission
TX_LOGS_FLAG, // Member can view transaction logs
TX_BALANCES_FLAG // Member can view account balances
}
};
let members = Some(vec![
Member {
// AUTHORITY_FLAG allows this member to modify permission settings
// TX_LOGS_FLAG allows viewing transaction logs
flags: AUTHORITY_FLAG | TX_LOGS_FLAG,
pubkey: *payer.key,
},
]);
// Note: Either the authority or permissioned_account can sign the transaction
// The signer depends on who has AUTHORITY_FLAG in the members list
CreatePermissionCpiBuilder::new(&permission_program)
.permissioned_account(&permissioned_account)
.permission(&permission)
.payer(&payer)
.system_program(&system_program)
.args(MembersArgs { members })
.invoke_signed(&[seed_refs.as_slice()])?;
use ephemeral_rollups_pinocchio::instruction::create_permission;
use ephemeral_rollups_pinocchio::types::{
Member,
MemberFlags,
MembersArgs,
};
use pinocchio::AccountView;
// Create members with specific flags
// AUTHORITY - Member can directly modify the permission
// TX_LOGS - Member can view transaction logs
// TX_BALANCES - Member can view account balances
// TX_MESSAGE - Member can view transaction messages
// ACCOUNT_SIGNATURES - Member can view account signatures
let mut flags = MemberFlags::new();
flags.set(MemberFlags::AUTHORITY);
flags.set(MemberFlags::TX_LOGS);
let member = Member {
flags,
pubkey: payer_address,
};
let members = vec![member];
let members_args = MembersArgs {
members: Some(&members),
};
// Prepare accounts: [permissioned_account, permission, payer, system_program]
let accounts: &[&AccountView] = &[
&permissioned_account,
&permission,
&payer,
&system_program,
];
// Create the permission
// Pass signer_seeds if permissioned_account is a PDA owned by your program
// Pass None if permissioned_account is an on-curve signer
create_permission(
accounts,
&permission_program_id,
members_args,
pda_signer_seeds, // Or None if permissioned_account is on-curve
)?;
import {
createCreatePermissionInstruction,
type Member,
AUTHORITY_FLAG, // Member can directly modify the permission
TX_LOGS_FLAG, // Member can view transaction logs
TX_BALANCES_FLAG, // Member can view account balances
} from "@magicblock-labs/ephemeral-rollups-sdk";
import { transaction, sendAndConfirmTransaction } from "@solana/kit";
const members: Member[] = [
{
// AUTHORITY_FLAG allows this member to modify permission settings
// TX_LOGS_FLAG allows viewing transaction logs
flags: AUTHORITY_FLAG | TX_LOGS_FLAG,
pubkey: payer.address,
},
];
// Either the authority or permissioned_account can sign the transaction
// The signer depends on who has AUTHORITY_FLAG in the members list
const createPermissionIx = await createCreatePermissionInstruction(
{
permissionedAccount: permissionedAccount.address,
payer: payer.address,
},
{
members,
}
);
const tx = transaction([createPermissionIx]);
const signature = await sendAndConfirmTransaction(
client,
tx,
[payer]
);
console.log("TX:", signature);
import {
Member,
AUTHORITY_FLAG, // Member can directly modify the permission
TX_LOGS_FLAG, // Member can view transaction logs
TX_BALANCES_FLAG, // Member can view account balances
createCreatePermissionInstruction,
} from "@magicblock-labs/ephemeral-rollups-sdk";
import { Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
const members: Member[] = [
{
// AUTHORITY_FLAG allows this member to modify permission settings
// TX_LOGS_FLAG allows viewing transaction logs
flags: AUTHORITY_FLAG | TX_LOGS_FLAG,
pubkey: payer.publicKey,
},
];
// Either the authority or permissioned_account can sign the transaction
// The signer depends on who has AUTHORITY_FLAG in the members list
const createPermissionIx = createCreatePermissionInstruction(
{
permissionedAccount: permissionedAccount.publicKey,
payer: payer.publicKey,
},
{
members,
}
);
const tx = new Transaction().add(createPermissionIx);
const txSig = await sendAndConfirmTransaction(connection, tx, [payer]);
console.log("TX:", txSig);
- 新しく委任されたアカウントのアクセス制御を初期化する
- authority メンバーとその権限を設定する
- 誰がトランザクション詳細を見られるかを定義する
MagicBlock の Delegation Program ユースケース:
DELeGGvXpWV2fqJUhqcF5ZSYMS4JTLjteaAMARRSaeSh を通じて permissioned account を委任し、低レイテンシーの Private Ephemeral Rollup 実行を有効にします。これらの公開バリデータは開発用として利用できます。委任命令には、 対象となる ER バリデータを必ず追加してください。
メインネット- アジア (as.magicblock.app):
MAS1Dt9qreoRMQ14YQuhg8UTZMMzDdKhmkZMECCzk57 - EU (eu.magicblock.app):
MEUGGrYPxKk17hCr7wpT6s8dtNokZj5U2L57vjYMS8e - 米国 (us.magicblock.app):
MUS3hc9TCw4cGC12vHNoYcCGzJG1txjgQLZWVoeNHNd - TEE (mainnet-tee.magicblock.app):
MTEWGuqxUpYZGFJQcp8tLN7x5v9BSeoFHYWQQ3n3xzo
- アジア (devnet-as.magicblock.app):
MAS1Dt9qreoRMQ14YQuhg8UTZMMzDdKhmkZMECCzk57 - EU (devnet-eu.magicblock.app):
MEUGGrYPxKk17hCr7wpT6s8dtNokZj5U2L57vjYMS8e - 米国 (devnet-us.magicblock.app):
MUS3hc9TCw4cGC12vHNoYcCGzJG1txjgQLZWVoeNHNd - TEE (devnet-tee.magicblock.app):
MTEWGuqxUpYZGFJQcp8tLN7x5v9BSeoFHYWQQ3n3xzo
- ローカル ER (localhost:7799):
mAGicPQYBMvcYveUZA5F5UNNwyHvfYh5xkLS2Fr1mev
- Rust SDK
- Pinocchio
- Kit
- Web3.js
use ephemeral_rollups_sdk::access_control::{
instructions::DelegatePermissionCpiBuilder
};
// Delegate the permission to enable low-latency Ephemeral Rollup execution
// Either authority (with AUTHORITY_FLAG) or permissioned_account can authorize
DelegatePermissionCpiBuilder::new(&permission_program)
.payer(&payer) // Pays for account creation
.authority(&payer, false) // Authority signer (has AUTHORITY_FLAG)
.permissioned_account(&permissioned_account, true) // or permissioned_account can sign
.permission(&permission)
.system_program(&system_program)
.owner_program(&owner_program)
.delegation_buffer(&delegation_buffer)
.delegation_record(&delegation_record)
.delegation_metadata(&delegation_metadata)
.delegation_program(&delegation_program)
.validator(&validator) // Validator that will execute the delegated state
.invoke_signed(&[seed_refs.as_slice()])?;
use ephemeral_rollups_pinocchio::instruction::delegate_permission;
use pinocchio::AccountView;
pub fn process_delegate_permission(
accounts: &[&AccountView],
permission_program: &pinocchio::Address,
authority_is_signer: bool,
permissioned_account_is_signer: bool,
) -> pinocchio::ProgramResult {
// Accounts: [payer, authority, permissioned_account, permission, system_program,
// owner_program, delegation_buffer, delegation_record,
// delegation_metadata, delegation_program, validator (optional)]
// Pass signer_seeds if permissioned_account is a PDA owned by your program
delegate_permission(
accounts,
permission_program,
authority_is_signer,
permissioned_account_is_signer,
signer_seeds, // Or None if permissioned_account is on-curve
)?;
Ok(())
}
import {
createDelegatePermissionInstruction,
PERMISSION_PROGRAM_ID,
} from "@magicblock-labs/ephemeral-rollups-sdk";
import { transaction, sendAndConfirmTransaction } from "@solana/kit";
// Delegate the permission to enable low-latency Ephemeral Rollup execution
// Either authority (with AUTHORITY_FLAG) or permissioned_account can authorize
const delegatePermissionIx = await createDelegatePermissionInstruction(
{
payer: payer.address, // Pays for account creation
authority: [payer.address, true], // Authority signer (has AUTHORITY_FLAG)
permissionedAccount: [permissionedAccount.address, false], // or permissioned_account can sign
ownerProgram: PERMISSION_PROGRAM_ID,
validator, // Validator that will execute the delegated state
}
);
const tx = transaction([delegatePermissionIx]);
const signature = await sendAndConfirmTransaction(
client,
tx,
[payer]
);
console.log("TX:", signature);
import {
PERMISSION_PROGRAM_ID,
createDelegatePermissionInstruction,
} from "@magicblock-labs/ephemeral-rollups-sdk";
import { Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
// Delegate the permission to enable low-latency Ephemeral Rollup execution
// Either authority (with AUTHORITY_FLAG) or permissioned_account can authorize
const delegatePermissionIx = createDelegatePermissionInstruction({
payer: payer.publicKey, // Pays for account creation
authority: [payer.publicKey, true], // Authority signer (has AUTHORITY_FLAG)
permissionedAccount: [permissionedAccount.publicKey, false], // or permissioned_account can sign
ownerProgram: PERMISSION_PROGRAM_ID,
validator, // Validator that will execute the delegated state
});
const tx = new Transaction().add(delegatePermissionIx);
const txSig = await sendAndConfirmTransaction(connection, tx, [payer]);
console.log("TX:", txSig);
- permissioned account に対する ER 実行を有効にする
- 状態変更を実行する特定のバリデータを指定する
- リアルタイムトランザクション処理のための委任を設定する
AUTHORITY_FLAGに基づき、authority またはpermissioned_accountのいずれかが署名する必要があります- バリデータは ER の速度でトランザクションを処理します
- コミット頻度により Solana への状態同期の頻度が決まります
- Private Ephemeral Rollup に委任された時点で permission は強制されます。適切なフラグを持つメンバーだけがアカウント状態にアクセスまたは変更できます
MagicBlock の Permission Program ユースケース:
ACLseoPoyC3cBqoUtkbjZ4aDrkurZW86v19pXz2XQnp1 を通じて、permission account 内の既存メンバーまたはそのフラグを変更します。- Rust SDK
- Pinocchio
- Kit
- Web3.js
use ephemeral_rollups_sdk::access_control::{
instructions::UpdatePermissionCpiBuilder,
structs::MembersArgs
};
// Update permission and modify members
// Either authority or permissioned_account must sign based on AUTHORITY_FLAG
UpdatePermissionCpiBuilder::new(&permission_program)
.authority(&payer, true) // authority can sign if they have AUTHORITY_FLAG
.permissioned_account(&permissioned_account, true) // or permissioned_account can sign
.permission(&permission)
// Setting members to None makes the permission public (temporarily visible)
// This is useful for transitional states during delegation/undeligation
.args(MembersArgs { members: None })
.invoke_signed(&[seed_refs.as_slice()])?;
use ephemeral_rollups_pinocchio::instruction::update_permission;
use ephemeral_rollups_pinocchio::types::{
Member,
MemberFlags,
MembersArgs,
};
use pinocchio::AccountView;
// Update permission with new member flags
// Either authority or permissioned_account must sign based on AUTHORITY_FLAG
let mut new_flags = MemberFlags::new();
new_flags.set(MemberFlags::TX_LOGS);
new_flags.set(MemberFlags::TX_BALANCES);
let updated_member = Member {
flags: new_flags,
pubkey: user_address,
};
let members = vec![updated_member];
let members_args = MembersArgs {
members: Some(&members),
};
// Prepare accounts: [authority, permissioned_account, permission]
let accounts: &[&AccountView] = &[
&authority,
&permissioned_account,
&permission,
];
// Update the permission
// Setting members to None makes the permission public (temporarily visible)
// Pass signer_seeds if permissioned_account is a PDA owned by your program
update_permission(
accounts,
&permission_program_id,
authority.is_signer(),
permissioned_account.is_signer(),
members_args,
signer_seeds, // Or None if permissioned_account is on-curve
)?;
import {
createUpdatePermissionInstruction,
type Member,
} from "@magicblock-labs/ephemeral-rollups-sdk";
import { transaction, sendAndConfirmTransaction } from "@solana/kit";
// Update permission and modify members
// Either authority or permissioned_account must sign based on AUTHORITY_FLAG
const updatePermissionIx = await createUpdatePermissionInstruction(
{
authority: [payer.address, true], // authority can sign if they have AUTHORITY_FLAG
permissionedAccount: [permissionedAccount.address, false], // or permissioned_account can sign
},
{
// Setting members to empty array or None makes the permission public (temporarily visible)
// This is useful for transitional states during delegation/undeligation
members: [],
}
);
const tx = transaction([updatePermissionIx]);
const signature = await sendAndConfirmTransaction(
client,
tx,
[payer]
);
console.log("TX:", signature);
import { createUpdatePermissionInstruction } from "@magicblock-labs/ephemeral-rollups-sdk";
import { Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
// Update permission and modify members
// Either authority or permissioned_account must sign based on AUTHORITY_FLAG
const updatePermissionIx = createUpdatePermissionInstruction(
{
authority: [payer.publicKey, true], // authority can sign if they have AUTHORITY_FLAG
permissionedAccount: [permissionedAccount.publicKey, false], // or permissioned_account can sign
},
{
// Setting members to empty array or None makes the permission public (temporarily visible)
// This is useful for transitional states during delegation/undeligation
members: [],
}
);
const tx = new Transaction().add(updatePermissionIx);
const txSig = await sendAndConfirmTransaction(connection, tx, [payer]);
console.log("TX:", txSig);
- permission group に新しいメンバーを追加する
- メンバー削除によって権限を取り消す
- メンバーフラグを変更してアクセスを許可または制限する
- メンバーを
Noneに設定してアカウントを一時的に可視化する
Private Ephemeral Rollup にリクエストする際は、まず認可を確立する必要があります:認可ステップ:アカウントの可視性:
Private Ephemeral Rollup(devnet)のエンドポイント:
https://devnet-tee.magicblock.app?token= {authToken}。{authToken} を TEE RPC から取得した認可トークンに置き換えてリクエストを送信してください。- TEE RPC の完全性を検証する: TDX quote と Intel 発行の証明書を使い、TEE RPC サーバーが正規の Intel TDX ハードウェア上で動作していることを確認する
- 認可トークンを要求する: challenge message に署名し、認可トークンを受け取る
- 接続を作成する: 認可トークンを header または query parameter として渡す
- Kit
- Web3.js
import {
verifyTeeRpcIntegrity,
getAuthToken,
} from "@magicblock-labs/ephemeral-rollups-sdk";
import { Connection } from "@magicblock-labs/ephemeral-rollups-kit";
import * as nacl from "tweetnacl";
const teeUrl = "https://devnet-tee.magicblock.app";
const teeWsUrl = "wss://tee.magicblock.app";
// 1. Verify the integrity of TEE RPC
const isVerified = await verifyTeeRpcIntegrity(teeUrl);
// 2. Get AuthToken before making request to TEE
const authToken = await getAuthToken(
teeUrl,
userPubkey,
(message: Uint8Array) =>
Promise.resolve(nacl.sign.detached(message, userSecretKey)),
);
// 3. Create connection with TEE using authorization token
const teeUserUrl = `${teeUrl}?token=${authToken.token}`;
const teeUserWsUrl = `${teeWsUrl}?token=${authToken.token}`;
const ephemeralConnection = await Connection.create(teeUserUrl, teeUserWsUrl);
import {
verifyTeeRpcIntegrity,
getAuthToken,
} from "@magicblock-labs/ephemeral-rollups-sdk";
import { Connection, Keypair } from "@solana/web3.js";
import * as nacl from "tweetnacl";
const teeUrl = "https://devnet-tee.magicblock.app";
const teeWsUrl = "wss://tee.magicblock.app";
// 1. Verify the integrity of TEE RPC
const isVerified = await verifyTeeRpcIntegrity(teeUrl);
// 2. Get AuthToken before making request to TEE
const authToken = await getAuthToken(
teeUrl,
userKeypair.publicKey,
(message: Uint8Array) =>
Promise.resolve(nacl.sign.detached(message, userKeypair.secretKey)),
);
// 3. Create connection with TEE
const teeUserUrl = `${teeUrl}?token=${authToken.token}`;
const teeUserWsUrl = `${teeWsUrl}?token=${authToken.token}`;
const connection = new Connection(teeUserUrl, {
wsEndpoint: teeUserWsUrl,
});
- デフォルトでは: すべてのアカウントは透過的で、認可された任意のユーザーがアクセスできます
- 権限設定後は: アカウントが permission system によって保護されると、すべてのリクエストでアクセス制御ルールが強制されます
- 適切なフラグを持つメンバーだけが permissioned accounts とトランザクションにアクセスまたは変更できます
- リクエストはバリデータ上でリアルタイムに実行されます
- メンバーフラグが各ユーザーの実行可能な操作を決定します
- 実行中でも権限は動的に更新できます
- 更新は Private Ephemeral Rollup に即時反映されます
Private Ephemeral Rollup 上の最新の permission state はアクセス制御を強制します。permission account を閉じる場合は、permission を Solana に委任解除する前に permission members を更新してください。⬆️ トップに戻る
- Rust SDK
- Pinocchio
- Kit
- Web3.js
use ephemeral_rollups_sdk::access_control::{
instructions::CommitAndUndelegatePermissionCpiBuilder
};
CommitAndUndelegatePermissionCpiBuilder::new(&permission_program)
.authority(&payer, false)
.permissioned_account(&permissioned_account, true)
.permission(&permission)
.magic_program(&magic_program)
.magic_context(&magic_context)
.invoke_signed(&[seed_refs.as_slice()])?;
use ephemeral_rollups_pinocchio::instruction::commit_and_undelegate_permission;
use pinocchio::AccountView;
pub fn process_commit_and_undelegate_permission(
accounts: &[&AccountView],
permission_program: &pinocchio::Address,
authority_is_signer: bool,
permissioned_account_is_signer: bool,
) -> pinocchio::ProgramResult {
// Accounts: [authority, permissioned_account, permission, magic_program, magic_context]
// Pass signer_seeds if permissioned_account is a PDA owned by your program
commit_and_undelegate_permission(
accounts,
permission_program,
authority_is_signer,
permissioned_account_is_signer,
signer_seeds, // Or None if permissioned_account is on-curve
)?;
Ok(())
}
import {
createCommitAndUndelegatePermissionInstruction,
} from "@magicblock-labs/ephemeral-rollups-sdk";
import { transaction, sendAndConfirmTransaction } from "@solana/kit";
const commitAndUndelegatePermissionIx =
await createCommitAndUndelegatePermissionInstruction({
authority: [payer.address, true],
permissionedAccount: [permissionedAccount.address, false],
});
const tx = transaction([commitAndUndelegatePermissionIx]);
const signature = await sendAndConfirmTransaction(
client,
tx,
[payer]
);
console.log("TX:", signature);
import { createCommitAndUndelegatePermissionInstruction } from "@magicblock-labs/ephemeral-rollups-sdk";
import { Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
const commitAndUndelegatePermissionIx =
createCommitAndUndelegatePermissionInstruction({
authority: [payer.publicKey, true],
permissionedAccount: [permissionedAccount.publicKey, false],
});
const tx = new Transaction().add(commitAndUndelegatePermissionIx);
const txSig = await sendAndConfirmTransaction(connection, tx, [payer]);
console.log("TX:", txSig);
permissioned account を閉じ、Solana 上の lamports を回収します。ユースケース:
- Rust SDK
- Pinocchio
- Kit
- Web3.js
use ephemeral_rollups_sdk::access_control::{
instructions::ClosePermissionCpiBuilder
};
// Close the permission account and reclaim lamports
// IMPORTANT: The permission must be undelegated to Solana first
// If delegated, call commit_and_undelegate before closing
ClosePermissionCpiBuilder::new(&permission_program)
.payer(&payer) // Receives reclaimed lamports
.authority(&payer, false) // Authority signer (has AUTHORITY_FLAG)
.permissioned_account(&permissioned_account, true) // or permissioned_account can sign
.permission(&permission) // The permission account to close
.invoke_signed(&[seed_refs.as_slice()])?;
use ephemeral_rollups_pinocchio::instruction::close_permission;
use pinocchio::AccountView;
pub fn process_close_permission(
accounts: &[&AccountView],
permission_program: &pinocchio::Address,
authority_is_signer: bool,
permissioned_account_is_signer: bool,
) -> pinocchio::ProgramResult {
// Accounts: [payer, authority, permissioned_account, permission]
// IMPORTANT: The permission must be undelegated to Solana first
// If the permission is still delegated, this operation will fail
// Pass signer_seeds if permissioned_account is a PDA owned by your program
close_permission(
accounts,
permission_program,
authority_is_signer,
permissioned_account_is_signer,
signer_seeds, // Or None if permissioned_account is on-curve
)?;
// The permission account lamports are transferred to the payer
Ok(())
}
import {
createClosePermissionInstruction,
} from "@magicblock-labs/ephemeral-rollups-sdk";
import { transaction, sendAndConfirmTransaction } from "@solana/kit";
// Close the permission account and reclaim lamports
// IMPORTANT: The permission must be undelegated to Solana first
// If delegated, call commit_and_undelegate before closing
const closePermissionIx = await createClosePermissionInstruction({
payer: payer.address, // Receives reclaimed lamports
authority: [payer.address, true], // Authority signer (has AUTHORITY_FLAG)
permissionedAccount: [permissionedAccount.address, false], // or permissioned_account can sign
});
const tx = transaction([closePermissionIx]);
const signature = await sendAndConfirmTransaction(
client,
tx,
[payer]
);
console.log("TX:", signature);
import { createClosePermissionInstruction } from "@magicblock-labs/ephemeral-rollups-sdk";
import { Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
// Close the permission account and reclaim lamports
// IMPORTANT: The permission must be undelegated to Solana first
// If delegated, call commit_and_undelegate before closing
const closePermissionIx = createClosePermissionInstruction({
payer: payer.publicKey, // Receives reclaimed lamports
authority: [payer.publicKey, true], // Authority signer (has AUTHORITY_FLAG)
permissionedAccount: [permissionedAccount.publicKey, false], // or permissioned_account can sign
});
const tx = new Transaction().add(closePermissionIx);
const txSig = await sendAndConfirmTransaction(connection, tx, [payer]);
console.log("TX:", txSig);
- 未使用の permission accounts を整理する
- 閉じたアカウントから SOL を回収する
- permission は先に Solana へ委任解除する必要があります
- 委任済みの場合、閉じる前に
commit_and_undelegateを呼び出します - lamports は payer に返却されます
ベストプラクティス
- Authority 管理: 常に少なくとも 1 人の信頼できるメンバーに
AUTHORITY_FLAGを割り当てる - 最小権限: 各メンバーには必要なフラグだけを付与する
- リアルタイム更新: permission は委任解除せずに Private Ephemeral Rollup 上でリアルタイム更新でき、動的なアクセス制御調整が可能
- クリーンアップ: 未使用の permission accounts を委任解除して閉じ、SOL を解放する
セキュリティ上の考慮事項
- 署名者の検証:
AUTHORITY_FLAGを持つメンバー、または permissioned account を持つプログラムだけが変更を認可できます - 公開アカウント: メンバーを
Noneに設定すると、アカウントは公開可視状態になります - デフォルト Authority: デフォルトでは、permissioned account の所有者が permission account の members に permission authority として追加されます
- 空のメンバー一覧:
membersフィールドが空リストに設定されると、permissioned account は完全に制限されて非公開になります。permission を変更できるのは所有者だけです - アクセス監査: メンバーフラグを使ってアクセスを監査・制御します
アクセス制御
きめ細かなアクセス制御
オンチェーンプライバシー
プライバシーの仕組みと概念
認可
認可フレームワーク
コンプライアンスフレームワーク
コンプライアンス基準とガイドライン

