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):
FnE6VJT5QNZdedZPnCoLsARgBwoE6DeJNjBs2H1gySXA
- ローカル 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):
FnE6VJT5QNZdedZPnCoLsARgBwoE6DeJNjBs2H1gySXA
- ローカル 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 を変更できるのは所有者だけです - アクセス監査: メンバーフラグを使ってアクセスを監査・制御します
アクセス制御
きめ細かなアクセス制御
オンチェーンプライバシー
プライバシーの仕組みと概念
認可
認可フレームワーク
コンプライアンスフレームワーク
コンプライアンス基準とガイドライン

