Auf dieser Seite wird beschrieben, wie Sie Cedar-Richtlinienregeln erstellen, um Transaktionen in der Policy Engine für Multi-Party Computation (MPC) zu validieren.
Die Policy Engine decodiert eingehende Transaktionsnutzlasten in einer sicheren vertrauenswürdigen Ausführungsumgebung (Trusted Execution Environment, TEE) und projiziert die Transaktionsabsichtsattribute auf den Cedar-Bewertungskontext.
Cedar-Regelstruktur
Wenn Sie Cedar-Regeln für die Policy Engine schreiben, geben Sie eine Regel mit einer verschachtelten Gruppe von Bedingungen an:
- Hauptkonto: Die logische Identität des Transaktionsanforderers (des Initiators der Transaktion) im Multi-Party Compute-Arbeitsbereich (z. B.
User::"alice") und nicht die Google Cloud IAM-Identität (Nutzer oder Dienstkonto), die die API aufruft. - Aktion: Die angeforderte kryptografische Aktion (z. B.
Action::"sign_transaction"). - Ressource: Das Ziel-Asset oder die Vorgangsklasse, für die der Vorgang ausgeführt wird (z. B.
Resource::"mpc_operation"). - Kontext: Die geparsten Transaktionsmetadaten und ‑parameter (zugänglich unter
context.transaction).
Referenz zum Ethereum-Transaktionsschema
Das protokollunabhängige Framework ermöglicht es, die Schemaprüfung in Regeln wegzulassen, damit sie in verschiedenen Blockchain-Netzwerken wiederverwendet werden können. Wenn Sie eine Regel explizit auf Ethereum-Transaktionsnutzlasten beschränken möchten, prüfen Sie Folgendes: context.transaction.schema == "ethereum.transaction.v2".
Die folgenden Attribute werden im context.transaction-Eintrag unterstützt:
| Attribut | Typ | Beschreibung |
|---|---|---|
schema |
String | Das Formatschema. Bei Ethereum-Transaktionen ist dies immer "ethereum.transaction.v2". |
operation |
String |
Der Transaktionsvorgangstyp. Unterstützte Werte:
|
chain_id |
String | Die ID des Ziel-Blockchain-Netzwerks (z. B. "1" für Ethereum Mainnet oder "11155111" für Sepolia Testnet). |
asset_symbol |
String | Das Tickersymbol des übertragenen Tokens (z. B. "ETH", "USDC", "DAI" oder "WBTC"). Bei nicht gelisteten Tokens wird "UNKNOWN" zurückgegeben. |
asset_contract_address |
String | Die Smart-Contract-Adresse des ERC-20-Tokens (im EIP-55-Prüfsummenformat mit Groß- und Kleinschreibung). Bei Standard-ETH-Übertragungen wird dies in einen leeren String ("") aufgelöst. |
recipient |
String | Die Zieladresse des Empfängers (im EIP-55-Prüfsummenformat mit Groß- und Kleinschreibung). Bei Tokengenehmigungen ist dies die Adresse des Ausgebenden. |
spend_amount_scaled |
Lang |
Der Token-Übertragungsbetrag wird auf eine feste Genauigkeit von 9 Dezimalstellen (Nanocoin-Format) normalisiert. Dadurch müssen beim Schreiben von Regeln keine unterschiedlichen Token-Dezimalstellen (z. B. 6, 8 oder 18) mehr berücksichtigt werden.
Berechnung: Multiplizieren Sie den menschenlesbaren Asset-Betrag (z. B. 1,5 ETH oder 5.000 USDC) mit 1.000.000.000 (109), um den Wert für Ihre Regel zu erhalten:
|
spend_amount_dust |
Lang | Der verbleibende Rest des Transaktionsbetrags, der unter den Schwellenwert für die Genauigkeit von 9 Dezimalstellen fällt. Bei Assets mit mehr als 9 Dezimalstellen (z. B. ETH mit 18 Dezimalstellen) enthält dieses Feld den unskalierten Sub-Gwei-Wert (die verbleibenden Wei). Bei Assets mit 9 oder weniger Dezimalstellen (z. B. USDC oder WBTC) ist dies immer 0. |
max_fee_atomic |
Lang | Die maximale Gesamttransaktionsgebühr (skaliert um 109, was Gwei entspricht). |
gas_limit |
Lang | Die maximale Menge an Gas, die für die Transaktionsausführung zugewiesen wird. |
destination_type |
String | Die Klassifizierung der Empfängeradresse. Unterstützte Werte: "EOA" (Standard-Nutzer-Wallet), "CONTRACT" (Smart Contract) oder "INTERNAL_TREASURY" (interner Vault). |
temporal_validity |
Lang | Die Nonce des Transaktionskontos (wird verwendet, um Replay-Angriffe auf Transaktionen zu verhindern). |
Referenz zum Bitcoin-Transaktionsschema
Wenn Sie eine Regel explizit auf Bitcoin BIP 174 PSBT-Transaktionsnutzlasten beschränken möchten, prüfen Sie Folgendes: context.transaction.schema == "bitcoin.transaction.v2".
Die folgenden Attribute werden im context.transaction-Eintrag unterstützt:
| Attribut | Typ | Beschreibung |
|---|---|---|
schema |
String | Das Formatschema. Bei Bitcoin-Transaktionen ist dies immer "bitcoin.transaction.v2". |
operation |
String |
Der Transaktionsvorgangstyp. Unterstützte Werte:
|
chain_id |
String | Der menschenlesbare Teil (HRP) des Bech32-Zielnetzwerks: "bc" (Bitcoin-Mainnet), "tb" (Testnet / Testnet4) oder "bcrt" (Regtest). |
asset_symbol |
String | Das Tickersymbol des Assets: "BTC". |
recipient |
String | Die primäre Zieladresse. Bei OP_RETURN-Transaktionen ist dies "unaddressable". Bei internen Konsolidierungs-Sweeps (100% Wechsel) wird dies in die erste Wechseladresse aufgelöst. |
spend_amount_scaled |
Lang |
Der Nettobetrag der ausgehenden Überweisung, normalisiert auf eine feste Genauigkeit von 9 Dezimalstellen (10-9-Einheiten). Da 1 Satoshi 10 Nanocoin-Einheiten entspricht (1 Sat = 10 Einheiten, 1 BTC = 109 Einheiten), werden interne Wechselgeldbeträge ausgeschlossen. Bei internen Sweeps / Transaktionen mit 100% Wechselgeld wird hier 0 ausgegeben.
|
max_fee_atomic |
Lang | Die berechnete Obergrenze für die Miner-Gebühr, normalisiert auf eine Genauigkeit von 9 Dezimalstellen: (∑ Eingaben − ∑ Ausgaben) × 10. |
destination_type |
String | Die Klassifizierung des Empfängerskripts. Unterstützte Werte: "P2WPKH" (Native SegWit), "P2TR" (Taproot), "P2PKH" (Legacy), "P2SH" (Nested SegWit / Script Hash), "TREASURY_CHANGE" (interne Änderung) oder "". |
temporal_validity |
Lang | Das Transaktionsfeld nLockTime. |
outputs |
Set<Record> | Der normalisierte Satz aller Transaktionsausgaben: [{ address: String, amount_scaled: Long, is_change: Bool }]. |
Wichtige Konzepte der Bitcoin-Richtlinie
Universelle 9-Dezimalstellen-Skalierung: Beträge in Bitcoin-Richtlinien verwenden eine normalisierte 9-Dezimalstellen-Nanocoin-Präzision (1 Sat = 10 Einheiten, 1 BTC = 109 Einheiten):
Amountscaled = Satoshis × 10 = BTC × 109
0.0005BTC (50.000 Satoshis) →500000(50.000 × 10)0.0025BTC (250.000 Satoshis) →2500000(250.000 × 10)1.0BTC (100.000.000 Satoshis) →1000000000(100.000.000 × 10)
Ausgabe für Wechselgeld trennen: Der Parser prüft BIP-32-Ableitungspfade (
m/.../1/*) und korreliert Eingabescripts, um Ausgaben für Wechselgeld automatisch zu identifizieren. Wechselgeldbeträge sind vonspend_amount_scaledausgeschlossen, damit Richtlinien für Ausgabenlimits strikt anhand des Nettowerts der ausgehenden Überweisungen an Dritte bewertet werden.Regel für einen einzelnen Empfänger, der nicht geändert werden darf: Um mehrdeutige Routingangriffe mit mehreren Empfängern zu verhindern, werden Transaktionen mit mehreren unterschiedlichen externen Drittanbieterempfängern abgelehnt (
ErrUnsupportedTx).
Beispiele für Cedar-Regeln
In den folgenden Beispielen wird gezeigt, wie Sie Zulassungslisten, Limitregeln und Replay-Grenzen mit Cedar für Ethereum- und Bitcoin-Transaktionen konfigurieren.
Ethereum-Beispiele
Die folgenden Regeln veranschaulichen gängige Richtlinienmuster für Ethereum- und ERC-20-Transaktionen.
1. Limit für direkte ETH-Übertragungen
Diese Regel erlaubt Alice, ETH auf der Base-Chain zu übertragen,und prüft,ob der skalierte Übertragungsbetrag 1,0 ETH (1.000.000.000 skalierte Gwei-Einheiten) nicht überschreitet.
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. Regel für die Zulassungsliste für ERC-20-Tokens
Diese Regel erlaubt USDC-Token-Übertragungen bis zu 5.000 USDC. Übertragungen werden auf Empfängeradressen auf einer Zulassungsliste beschränkt. Da bei Cedar-Strings die Groß-/Kleinschreibung berücksichtigt wird, muss die Empfängeradresse dem EIP-55-Format mit Groß- und Kleinschreibung entsprechen.
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. Smart Contract- und DeFi-Aufruf-Fallbacks
Diese Regel erlaubt allgemeine Vertragsinteraktionen (wie Staking oder Swapping) ohne Betragsbeschränkungen, sofern es sich nicht um Übertragungsvorgänge handelt, bei denen Vermögenswerte ausgegeben werden.
permit (
principal == User::"alice",
action == Action::"sign_transaction",
resource == Resource::"mpc_operation"
)
when {
context.transaction.operation == "CONTRACT_CALL"
};
4. Strikter Schutz vor Wiederholungsangriffen (Chain-ID-Grenze)
Um Replay-Angriffe zu verhindern, bei denen eine für eine Testnet-Chain signierte Nutzlast noch einmal in Produktions-Mainnets gesendet wird, können Sie Ihre Regel auf eine bestimmte Chain-ID beschränken (z.B. 11155111 für Sepolia).
permit (
principal == User::"alice",
action == Action::"sign_transaction",
resource == Resource::"mpc_operation"
)
when {
context.transaction.chain_id == "11155111"
};
Bitcoin-Beispiele
Die folgenden Regeln veranschaulichen gängige Richtlinienmuster für Bitcoin-PSBT-Transaktionen.
1. Ausgabenlimit und Obergrenze für Miner-Gebühren
Diese Regel erlaubt direkte Bitcoin-Überweisungen (BTC), bei denen der Nettobetrag der ausgehenden Überweisung 0,0025 BTC (250.000 Satoshis → 2.500.000 skalierte Einheiten) und die Miner-Gebühr 10.000 Satoshis (100.000 atomare Einheiten) nicht überschreitet.
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. Zulassungsliste für SegWit- (P2WPKH) und Taproot-Adressen (P2TR)
Diese Regel beschränkt Bitcoin-Übertragungen auf eine genehmigte SegWit- oder Taproot-Zieladresse.
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-Konsolidierung und Treasury-Sweep
Diese Regel erlaubt interne UTXO-Konsolidierungen, bei denen alle Ausgaben an interne Wechseladressen (destination_type == "TREASURY_CHANGE" und spend_amount_scaled == 0) zurückgegeben werden, und begrenzt gleichzeitig die Konsolidierungsgebühr.
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. Prüfung des Ausgabesatzes
Mit dieser Regel wird geprüft, ob der Transaktionsausgabesatz eine bestimmte Zielausgabe und einen bestimmten Betrag enthält.
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. Netzwerkbereich (Mainnet im Vergleich zu Testnet)
Diese Regel beschränkt die Autorisierung auf Bitcoin Testnet-Transaktionen (tb) und verhindert die Ausführung im 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-Datenverankerung
Diese Regel erlaubt nicht auszugebende OP_RETURN-Datenverankerungstransaktionen (spend_amount_scaled == 0 und recipient == "unaddressable") und erzwingt eine strenge Gebührenobergrenze.
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
};
Sicherheitsmaßnahmen für Parser
Um Transaktionsvorgänge in Produktionsumgebungen zu schützen, parst die Policy Engine Nutzlasten strikt und lehnt ungültige Strukturen auf der Gateway-Ebene ab, bevor Cedar-Regeln ausgewertet werden:
- Erzwingung der Basiswährung mit dem Wert null: Der Parser lehnt Ethereum-Token-Übertragungsvorgänge (
TOKEN_TRANSFER) explizit ab, bei denen auch versucht wird, Basisübertragungs-Assets mit einem Wert ungleich null zu bündeln. So wird verhindert, dass schädliche Nutzlasten Standard-Basis-Asset-Werte übertragen, während die Transaktion als Standard-Token-Übertragung dargestellt wird. - UTXO- und Witness-Verifizierung: Bei Bitcoin-PSBT-Transaktionen prüft der Parser, ob alle Eingaben gültige
witness_utxo-Daten liefern. So wird verhindert, dass die Gebührenberechnung manipuliert oder eine nicht verifizierte Signatur verwendet wird. - Überprüfung des Skripts für die Wechselgeldausgabe: Interne Wechselgeldausgaben müssen mit einem Eingabeskript-Pubkey oder einem bekannten BIP-32-Wechselgeldpfad (
m/.../1/*) übereinstimmen. Nutzlasten, die versuchen, Wechselgeldausgaben an Adressen von Drittanbietern zu fälschen, schlagen fehl. - Erzwingung eines einzelnen externen Empfängers:Bitcoin-Nutzlasten mit mehreren externen Zieladressen, die keine Wechselgeldadressen sind, werden abgelehnt (
ErrUnsupportedTx), um eine mehrdeutige Autorisierung von Richtlinien für mehrere Empfänger zu verhindern. - Schutz vor Integer-Überlauf und -Unterlauf: Nonces, Locktimes, Gas- oder Gebührenlimits und Beträge, die die Sicherheitsgrenzen (
MaxInt64) überschreiten oder Unterläufe erzeugen (z. B. wenn der Gesamtausgabewert den Gesamteingabewert überschreitet), werden sofort abgelehnt. - Fehlende Gebührenbestätigung: Transaktionen, bei denen keine korrekten Miner-Gebühren oder Gas-Parameter definiert sind, werden automatisch abgelehnt.