בדף הזה מוסבר איך ליצור כללי מדיניות ב-Cedar כדי לאמת עסקאות ב-Policy Engine של חישוב רב-משתתפים (MPC).
Policy Engine מפענח את המטען הייעודי (payload) של העסקאות הנכנסות בתוך סביבת מחשוב אמינה (TEE) ומקרין את מאפייני כוונת העסקה על הקשר ההערכה של Cedar.
מבנה הכללים של Cedar
כשכותבים כללי Cedar ל-Policy Engine, מציינים כלל באמצעות קבוצה של תנאים בתצוגת עץ:
- חשבון משתמש: הזהות הלוגית של מבקש העסקה (היוזם של העסקה) בסביבת העבודה של החישוב הרב-משתתפים (לדוגמה,
User::"alice"), ולא זהות ה-IAM (חשבון משתמש או חשבון שירות) שקוראת ל-API. Google Cloud - פעולה: הפעולה הקריפטוגרפית שהתבקשה (לדוגמה,
Action::"sign_transaction"). - משאב: הנכס או סוג הפעולה שמתבצעת (לדוגמה,
Resource::"mpc_operation"). - הקשר: המטא-נתונים והפרמטרים המנותחים של העסקה (נגישים דרך
context.transaction).
הפניה לסכימה של עסקאות ב-Ethereum
ה-framework שלא תלוי בפרוטוקול מאפשר לכללים להשמיט את בדיקת הסכימה כדי להמשיך להשתמש בהם ברשתות בלוקצ'יין שונות. עם זאת, כדי להגביל באופן מפורש כלל למטען ייעודי (payload) של עסקאות ב-Ethereum, צריך לבדוק את: context.transaction.schema == "ethereum.transaction.v2".
אפשר להשתמש במאפיינים הבאים ברשומה context.transaction:
| מאפיין | סוג | תיאור |
|---|---|---|
schema |
String | סכימת הפורמט. בעסקאות אתריום, הערך הזה הוא תמיד "ethereum.transaction.v2". |
operation |
String |
סוג הפעולה של העסקה. ערכים נתמכים:
|
chain_id |
String | מזהה רשת הבלוקצ'יין לטירגוט (לדוגמה, "1" ל-Ethereum Mainnet או "11155111" ל-Sepolia Testnet). |
asset_symbol |
String | סימול המניה של הטוקן שמועבר (לדוגמה, "ETH", "USDC", "DAI" או "WBTC"). טוקנים לא רשומים מחזירים את הערך "UNKNOWN". |
asset_contract_address |
String | כתובת החוזה החכם של טוקן ERC-20 (בפורמט סיכום ביקורת (checksum) של EIP-55 עם אותיות רישיות וקטנות). הערך הזה הופך למחרוזת ריקה ("") בהעברות ETH רגילות. |
recipient |
String | כתובת הנמען ביעד (בפורמט סיכום ביקורת (checksum) של EIP-55 עם אותיות רישיות וקטנות). באישורי טוקנים, זה מייצג את כתובת המשלם. |
spend_amount_scaled |
ארוכה |
סכום העברת הטוקנים מנורמל לדיוק קבוע של 9 ספרות אחרי הנקודה העשרונית (פורמט nanocoin), כך שלא צריך לעקוב אחרי מספרים עשרוניים שונים של טוקנים (כמו 6, 8 או 18) כשכותבים כללים.
איך מחשבים: מכפילים את סכום הנכס שקריא לאנשים (למשל, 1.5 ETH או 5,000 USDC) ב-1,000,000,000 (109) כדי לקבל את הערך של הכלל:
|
spend_amount_dust |
ארוכה | השארית שנותרה מסכום העסקה, שנמוכה מסף הדיוק של 9 ספרות אחרי הנקודה העשרונית. לנכסים עם יותר מ-9 ספרות אחרי הנקודה העשרונית (כמו ETH, שיש לו 18), השדה הזה מכיל את הערך של sub-Gwei ללא קנה מידה (ה-Wei שנותר). הערך הזה הוא תמיד 0 לנכסים עם 9 ספרות עשרוניות או פחות (כמו USDC או WBTC). |
max_fee_atomic |
ארוכה | התקרה המקסימלית של עמלה על עסקאות כוללות (בקנה מידה של 109, שמייצג Gwei). |
gas_limit |
ארוכה | הכמות המקסימלית של גז שמוקצית לביצוע העסקה. |
destination_type |
String | הסיווג של כתובת הנמען. ערכים נתמכים: "EOA" (ארנק משתמש רגיל), "CONTRACT" (חוזה חכם) או "INTERNAL_TREASURY" (כספת פנימית). |
temporal_validity |
ארוכה | המספר החד-פעמי של חשבון העסקה (משמש למניעת התקפות של הפעלה מחדש של עסקאות). |
הסבר על הסכימה של עסקאות בביטקוין
כדי להגביל כלל באופן מפורש למטעני נתונים של עסקאות Bitcoin BIP 174 PSBT, צריך לבדוק את: context.transaction.schema == "bitcoin.transaction.v2".
אפשר להשתמש במאפיינים הבאים ברשומה context.transaction:
| מאפיין | סוג | תיאור |
|---|---|---|
schema |
String | סכימת הפורמט. בעסקאות בביטקוין, הערך הזה הוא תמיד "bitcoin.transaction.v2". |
operation |
String |
סוג הפעולה של העסקה. ערכים נתמכים:
|
chain_id |
String | החלק הקריא לאנשים (HRP) של Bech32 ברשת היעד: "bc" (Bitcoin Mainnet), "tb" (Testnet / Testnet4) או "bcrt" (Regtest). |
asset_symbol |
String | סימול הנכס: "BTC". |
recipient |
String | כתובת היעד הראשית. בעסקאות ב-OP_RETURN, זה "unaddressable". בסוויפים פנימיים לאיחוד (שינוי של 100%), הכתובת הזו היא כתובת השינוי הראשונה. |
spend_amount_scaled |
ארוכה |
סכום ההעברה נטו החוצה, מנורמל לדיוק קבוע של 9 ספרות אחרי הנקודה העשרונית (יחידות של 10-9). מכיוון שסאטושי אחד שווה ל-10 יחידות ננו-מטבע (סאטושי אחד = 10 יחידות, ביטקוין אחד = 109 יחידות), סכומי השינוי הפנימיים לא נכללים. במקרה של עסקאות פנימיות של העברת יתרה או עסקאות של 100% עודף, הערך הוא 0.
|
max_fee_atomic |
ארוכה | תקרת העמלה המחושבת לכורה, מנורמלת לדיוק של 9 ספרות אחרי הנקודה העשרונית: (∑ קלט − ∑ פלט) × 10. |
destination_type |
String | סיווג הכתב של הנמען. ערכים נתמכים: "P2WPKH" (Native SegWit), "P2TR" (Taproot), "P2PKH" (Legacy), "P2SH" (Nested SegWit / Script Hash), "TREASURY_CHANGE" (internal change sweep) או "". |
temporal_validity |
ארוכה | השדה nLockTime של העסקה. |
outputs |
Set<Record> | הקבוצה המנורמלת של כל פלטי העסקאות: [{ address: String, amount_scaled: Long, is_change: Bool }]. |
מושגי מדיניות מרכזיים בנושא ביטקוין
חישוב אוניברסלי של קנה מידה עם 9 ספרות אחרי הנקודה העשרונית: הסכומים במדיניות של ביטקוין מנורמלים ל-9 ספרות אחרי הנקודה העשרונית (1 סאטושי = 10 יחידות, 1 ביטקוין = 109 יחידות):
Amountscaled = Satoshis × 10 = BTC × 109
-
0.0005(50,000 סאטושי) ←500000(50,000 × 10) -
0.0025BTC (250,000 סאטושי) ←2500000(250,000 × 10) -
1.0BTC (100,000,000 סאטושי) ←1000000000(100,000,000 × 10)
-
הפרדת פלט של עודף: המנתח בודק את נתיבי הנגזרת של BIP-32 (
m/.../1/*) ומתאים בין סקריפטים של קלט כדי לזהות באופן אוטומטי פלטים של עודף פנימי. סכומי העודף לא נכללים ב-spend_amount_scaled, כדי לוודא שהמדיניות של תקרת ההוצאות בודקת רק את הערך נטו של ההעברות היוצאות לצדדים שלישיים.כלל נמען יחיד ללא שינוי: כדי למנוע התקפות ניתוב מעורפלות עם כמה נמענים, עסקאות שמכילות כמה נמענים חיצוניים נפרדים של צד שלישי נכשלות ונסגרות (
ErrUnsupportedTx).
דוגמאות לכללים ב-Cedar
בדוגמאות הבאות מוסבר איך להגדיר רשימות היתרים, כללי הגבלה וגבולות להפעלה מחדש באמצעות Cedar לעסקאות ב-Ethereum ובביטקוין.
דוגמאות ל-Ethereum
הכללים הבאים ממחישים דפוסי מדיניות נפוצים לעסקאות ב-Ethereum וב-ERC-20.
1. מגבלת העברה ישירה של ETH
הכלל הזה מאפשר לאליס להעביר ETH בשרשרת בסיס, ובודק שסכום ההעברה המותאם לא חורג מ-1.0 ETH (1,000,000,000 יחידות Gwei מותאמות).
permit (
principal == User::"alice",
action == Action::"sign_transaction",
resource == Resource::"mpc_operation"
)
when {
context.transaction.operation == "NATIVE_TRANSFER" &&
context.transaction.asset_symbol == "ETH" &&
context.transaction.spend_amount_scaled <= 1000000000
};
2. כלל רשימת ההיתרים של אסימוני ERC-20
הכלל הזה מאפשר העברות של טוקנים מסוג USDC עד לסכום של 5,000 USDC. היא מגבילה את ההעברות לכתובת של נמען ברשימת היתרים. חשוב לזכור שהמחרוזות ב-Cedar הן תלויות אותיות רישיות, ולכן כתובת הנמען חייבת להתאים לפורמט EIP-55 שמשלב אותיות רישיות וקטנות.
permit (
principal == User::"alice",
action == Action::"sign_transaction",
resource == Resource::"mpc_operation"
)
when {
context.transaction.operation == "TOKEN_TRANSFER" &&
context.transaction.asset_symbol == "USDC" &&
context.transaction.recipient == "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B" &&
context.transaction.spend_amount_scaled <= 5000000000000
};
3. חוזים חכמים ו-DeFi (פיננסים מבוזרים)
הכלל הזה מאפשר אינטראקציות כלליות עם חוזים (כמו סטייקינג או החלפה) בלי הגבלות על הסכום, בתנאי שהן לא פעולות העברה של הוצאת נכסים.
permit (
principal == User::"alice",
action == Action::"sign_transaction",
resource == Resource::"mpc_operation"
)
when {
context.transaction.operation == "CONTRACT_CALL"
};
4. הגנה מחמירה מפני הפעלה חוזרת (גבול מזהה הרשת)
כדי למנוע התקפות של הפעלה מחדש של עסקאות, שבהן מטען ייעודי (payload) שנחתם עבור רשת בדיקה נשלח מחדש ברשתות ראשיות בסביבת הייצור, אפשר להגדיר את הכלל למזהה רשת ספציפי (למשל 11155111 עבור Sepolia).
permit (
principal == User::"alice",
action == Action::"sign_transaction",
resource == Resource::"mpc_operation"
)
when {
context.transaction.chain_id == "11155111"
};
דוגמאות לביטקוין
הכללים הבאים ממחישים דפוסי מדיניות נפוצים לעסקאות PSBT בביטקוין.
1. תקרת הוצאות ותקרת עמלת כרייה
הכלל הזה מאפשר העברות ישירות של ביטקוין (BTC) שבהן סכום ההעברה נטו לא עולה על 0.0025 ביטקוין (250,000 סאטושי ← 2,500,000 יחידות מותאמות) ועמלת הכרייה לא עולה על 10,000 סאטושי (100,000 יחידות אטומיות).
permit (
principal == User::"alice",
action == Action::"sign_transaction",
resource == Resource::"mpc_operation"
)
when {
context.transaction.operation == "NATIVE_TRANSFER" &&
context.transaction.asset_symbol == "BTC" &&
context.transaction.spend_amount_scaled <= 2500000 &&
context.transaction.max_fee_atomic <= 100000
};
2. רשימת היתרים של כתובות SegWit (P2WPKH) ו-Taproot (P2TR)
הכלל הזה מגביל את ההעברות של ביטקוין לכתובת יעד מאושרת של SegWit או Taproot.
permit (
principal == User::"alice",
action == Action::"sign_transaction",
resource == Resource::"mpc_operation"
)
when {
context.transaction.schema == "bitcoin.transaction.v2" &&
(context.transaction.destination_type == "P2WPKH" || context.transaction.destination_type == "P2TR") &&
context.transaction.recipient == "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
};
3. איחוד UTXO ואיסוף כספים
הכלל הזה מאפשר סריקות פנימיות לאיחוד UTXO שבהן כל הפלטים חוזרים לכתובות פנימיות של עודף (destination_type == "TREASURY_CHANGE" ו-spend_amount_scaled == 0), תוך הגבלת עמלת האיחוד.
permit (
principal == User::"alice",
action == Action::"sign_transaction",
resource == Resource::"mpc_operation"
)
when {
context.transaction.schema == "bitcoin.transaction.v2" &&
context.transaction.destination_type == "TREASURY_CHANGE" &&
context.transaction.spend_amount_scaled == 0 &&
context.transaction.max_fee_atomic <= 50000
};
4. בדיקת קבוצת הפלט
הכלל הזה מאמת שקבוצת הפלט של העסקה מכילה פלט יעד וסכום ספציפיים.
permit (
principal == User::"alice",
action == Action::"sign_transaction",
resource == Resource::"mpc_operation"
)
when {
context.transaction.outputs.contains({
address: "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
amount_scaled: 500000,
is_change: false
})
};
5. היקף הרשת (Mainnet לעומת Testnet)
הכלל הזה מגביל את ההרשאה לעסקאות ב-Bitcoin Testnet (tb), ומונע ביצוע ב-Bitcoin Mainnet (bc).
permit (
principal == User::"alice",
action == Action::"sign_transaction",
resource == Resource::"mpc_operation"
)
when {
context.transaction.schema == "bitcoin.transaction.v2" &&
context.transaction.chain_id == "tb"
};
6. עיגון נתונים של OP_RETURN
הכלל הזה מאפשר עסקאות עיגון נתונים של OP_RETURN שלא ניתן להוציא (spend_amount_scaled == 0 ו-recipient == "unaddressable"), ואוכף מגבלת עמלה מחמירה.
permit (
principal == User::"alice",
action == Action::"sign_transaction",
resource == Resource::"mpc_operation"
)
when {
context.transaction.operation == "OP_RETURN" &&
context.transaction.recipient == "unaddressable" &&
context.transaction.spend_amount_scaled == 0 &&
context.transaction.max_fee_atomic <= 10000
};
אמצעי הגנה על בטיחות המנתח
כדי להגן על פעולות של עסקאות בסביבות ייצור, Policy Engine מנתח את המטענים הייעודיים (payloads) באופן קפדני ודוחה מבנים לא חוקיים בשכבת השער לפני שהוא מעריך את כללי Cedar:
- אכיפת מטבע בסיס עם ערך אפס: המנתח דוחה באופן מפורש פעולות העברה של אסימוני אתריום (
TOKEN_TRANSFER) שמנסות גם לאגד נכסי העברה בסיסיים עם ערך שאינו אפס. כך אפשר למנוע ממטענים זדוניים להעביר ערכים סטנדרטיים של נכסי בסיס, תוך הצגת העסקה כהעברת טוקן רגילה. - אימות UTXO ו-Witness: בעסקאות PSBT של ביטקוין, המנתח מאמת שכל הקלטים מספקים נתוני
witness_utxoתקינים, כדי למנוע זיוף של חישוב העמלות או חתימה לא מאומתת. - אימות סקריפט של פלט שינוי: פלטים של שינויים פנימיים חייבים להתאים למפתח ציבורי של סקריפט קלט או לנתיב שינוי BIP-32 מוכר (
m/.../1/*). מטען ייעודי (payload) שמנסה לזייף פלטים של שינויים לכתובות של צד שלישי נכשל ונסגר. - אכיפה של נמען חיצוני יחיד: מטען ייעודי (payload) של ביטקוין שמכיל כמה כתובות יעד חיצוניות שלא משתנות נכשל במצב סגור (
ErrUnsupportedTx) כדי למנוע הרשאה לא ברורה של מדיניות עם כמה נמענים. - הגנה מפני גלישה חיובית ושלילית של מספרים שלמים: מספרים חד-פעמיים, זמני נעילה, מכסות גז או עמלות וסכומים שחורגים מגבולות הבטיחות (
MaxInt64) או מייצרים גלישה שלילית (כמו ערך פלט כולל שחורג מערך הקלט הכולל) נדחים באופן מיידי. - אימות עמלות חסרות: עסקאות שלא מוגדרות בהן עמלות כורים או פרמטרים של גז נכשלות באופן אוטומטי.