Cette page explique comment créer des règles de stratégie Cedar pour valider les transactions dans le moteur de stratégies de calcul multipartite (MPC).
Le moteur de stratégies décode les charges utiles des transactions entrantes dans un environnement d'exécution sécurisé (TEE) et projette les attributs d'intention de transaction sur le contexte d'évaluation Cedar.
Structure des règles Cedar
Lorsque vous écrivez des règles Cedar pour le moteur de stratégies, vous spécifiez une règle à l'aide d'un ensemble de conditions imbriquées :
- Compte principal : identité logique du demandeur de la transaction (l'initiateur de la transaction) dans l'espace de travail de calcul multipartite (par exemple,
User::"alice"), plutôt que l'identité IAM Google Cloud (utilisateur ou compte de service) appelant l'API. - Action : action cryptographique demandée (par exemple,
Action::"sign_transaction"). - Ressource : classe d'élément ou d'opération cible sur laquelle l'opération est effectuée (par exemple,
Resource::"mpc_operation"). - Contexte : métadonnées et paramètres de transaction analysés (accessibles sous
context.transaction).
Référence du schéma des transactions Ethereum
Le framework indépendant du protocole permet aux règles d'omettre la vérification du schéma pour rester réutilisables sur différents réseaux de blockchain. Toutefois, pour limiter explicitement une règle aux charges utiles de transaction Ethereum, cochez context.transaction.schema == "ethereum.transaction.v2".
Les attributs suivants sont acceptés dans l'enregistrement context.transaction :
| Attribut | Type | Description |
|---|---|---|
schema |
Chaîne | Schéma du format. Pour les transactions Ethereum, la valeur est toujours "ethereum.transaction.v2". |
operation |
Chaîne |
Type d'opération de transaction. Valeurs acceptées :
|
chain_id |
Chaîne | ID du réseau de blockchain cible (par exemple, "1" pour le réseau principal Ethereum ou "11155111" pour le réseau de test Sepolia). |
asset_symbol |
Chaîne | Symbole du jeton transféré (par exemple, "ETH", "USDC", "DAI" ou "WBTC"). Les jetons non listés renvoient "UNKNOWN". |
asset_contract_address |
Chaîne | L'adresse du contrat intelligent du jeton ERC-20 (au format de somme de contrôle EIP-55 mixte). Cette valeur est résolue en une chaîne vide ("") pour les transferts ETH standards. |
recipient |
Chaîne | L'adresse du destinataire (au format de somme de contrôle EIP-55 mixte). Pour les approbations de jetons, cela représente l'adresse du dépensier. |
spend_amount_scaled |
Long |
Montant du transfert de jetons normalisé à une précision fixe de 9 décimales (format nanocoin), ce qui évite d'avoir à suivre les différentes décimales des jetons (par exemple, 6, 8 ou 18) lors de l'écriture des règles.
Calcul : multipliez le montant de l'élément lisible par l'humain (par exemple, 1,5 ETH ou 5 000 USDC) par 1 000 000 000 (109) pour obtenir la valeur de votre règle :
|
spend_amount_dust |
Long | Le reste du montant de la transaction qui est inférieur au seuil de précision de neuf décimales. Pour les éléments comportant plus de neuf décimales (comme l'ETH, qui en comporte 18), ce champ contient la valeur sub-Gwei non mise à l'échelle (le Wei restant). Cette valeur est toujours 0 pour les actifs comportant neuf décimales ou moins (comme USDC ou WBTC). |
max_fee_atomic |
Long | Plafond maximal des frais de transaction totaux (multiplié par 109, représentant le Gwei). |
gas_limit |
Long | Quantité maximale de gaz allouée à l'exécution de la transaction. |
destination_type |
Chaîne | Classification de l'adresse du destinataire. Valeurs acceptées : "EOA" (portefeuille utilisateur standard), "CONTRACT" (contrat intelligent) ou "INTERNAL_TREASURY" (coffre-fort interne). |
temporal_validity |
Long | Nonce du compte de transaction (utilisé pour empêcher les attaques par rejeu de transaction). |
Référence du schéma de transaction Bitcoin
Pour limiter explicitement une règle aux charges utiles de transaction PSBT Bitcoin BIP 174, cochez context.transaction.schema == "bitcoin.transaction.v2".
Les attributs suivants sont acceptés dans l'enregistrement context.transaction :
| Attribut | Type | Description |
|---|---|---|
schema |
Chaîne | Schéma du format. Pour les transactions Bitcoin, la valeur est toujours "bitcoin.transaction.v2". |
operation |
Chaîne |
Type d'opération de transaction. Valeurs acceptées :
|
chain_id |
Chaîne | Partie lisible par l'humain (HRP) Bech32 du réseau cible : "bc" (Bitcoin Mainnet), "tb" (Testnet / Testnet4) ou "bcrt" (Regtest). |
asset_symbol |
Chaîne | Le symbole boursier de l'actif : "BTC". |
recipient |
Chaîne | Adresse de destination principale. Pour les transactions OP_RETURN, il s'agit de "unaddressable". Pour les balayages de consolidation internes (modification à 100 %), cela correspond à la première adresse de modification. |
spend_amount_scaled |
Long |
Montant net du transfert sortant normalisé à une précision fixe de neuf décimales (10-9 unités). Comme un satoshi équivaut à 10 unités de nanocoin (1 sat = 10 unités, 1 BTC = 109 unités), les montants de monnaie interne sont exclus. Pour les transactions de balayage interne / modification à 100 %, la valeur est 0.
|
max_fee_atomic |
Long | Plafond des frais de mineur calculé, normalisé avec une précision de neuf décimales : (∑ Entrées − ∑ Sorties) × 10. |
destination_type |
Chaîne | Classification du script du destinataire. Valeurs acceptées : "P2WPKH" (SegWit natif), "P2TR" (Taproot), "P2PKH" (ancien), "P2SH" (SegWit imbriqué / hachage de script), "TREASURY_CHANGE" (balayage de modification interne) ou "". |
temporal_validity |
Long | Champ nLockTime de la transaction. |
outputs |
Set<Record> | Ensemble normalisé de toutes les sorties de transaction : [{ address: String, amount_scaled: Long, is_change: Bool }]. |
Concepts fondamentaux des règles Bitcoin
Mathématiques de mise à l'échelle universelle à 9 décimales : Les montants des règles Bitcoin utilisent une précision normalisée de 9 décimales (1 sat = 10 unités, 1 BTC = 109 unités) :
Montantmis à l'échelle = 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)
Séparation des sorties de monnaie : l'analyseur inspecte les chemins de dérivation BIP-32 (
m/.../1/*) et met en corrélation les scripts d'entrée pour identifier automatiquement les sorties de monnaie internes. Les montants de monnaie sont exclus despend_amount_scaled, ce qui garantit que les règles de limite de dépense sont évaluées strictement par rapport à la valeur nette sortante transférée à des tiers.Règle de destinataire unique sans modification : pour éviter les attaques de routage ambiguës impliquant plusieurs destinataires, les transactions contenant plusieurs destinataires tiers externes distincts échouent (
ErrUnsupportedTx).
Exemples de règles Cedar
Les exemples suivants montrent comment configurer des listes d'autorisation, des règles de limite et des limites de relecture à l'aide de Cedar pour les transactions Ethereum et Bitcoin.
Exemples Ethereum
Les règles suivantes illustrent des modèles de règles courants pour les transactions Ethereum et ERC-20.
1. Limite de transfert direct d'ETH
Cette règle autorise Alice à transférer des ETH de la chaîne de base, en vérifiant que le montant du transfert mis à l'échelle ne dépasse pas 1,0 ETH (1 000 000 000 d'unités Gwei mises à l'échelle).
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. Règle de liste d'autorisation des jetons ERC-20
Cette règle autorise les transferts de jetons USDC jusqu'à 5 000 USDC. Il limite les transferts à une adresse de destinataire figurant sur une liste d'autorisation. Notez que, comme les chaînes Cedar sont sensibles à la casse, l'adresse du destinataire doit correspondre au format EIP-55, qui mélange majuscules et minuscules.
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. Contrats intelligents et solutions de remplacement pour les appels DeFi
Cette règle autorise les interactions générales avec les contrats (comme le staking ou le swapping) sans restriction de montant, à condition qu'il ne s'agisse pas d'opérations de transfert de dépenses d'actifs.
permit (
principal == User::"alice",
action == Action::"sign_transaction",
resource == Resource::"mpc_operation"
)
when {
context.transaction.operation == "CONTRACT_CALL"
};
4. Protection stricte contre les attaques de répétition (limite de l'ID de chaîne)
Pour éviter les attaques par rejeu de transaction, où une charge utile signée pour une chaîne testnet est soumise à nouveau sur les mainnets de production, vous pouvez limiter la portée de votre règle à un ID de chaîne spécifique (par exemple, 11155111 pour Sepolia).
permit (
principal == User::"alice",
action == Action::"sign_transaction",
resource == Resource::"mpc_operation"
)
when {
context.transaction.chain_id == "11155111"
};
Exemples de requêtes sur le Bitcoin
Les règles suivantes illustrent des modèles de règles courants pour les transactions PSBT Bitcoin.
1. Limite de dépense et plafond des frais de minage
Cette règle autorise les transferts directs de Bitcoin (BTC) lorsque le montant net du transfert sortant ne dépasse pas 0,0025 BTC (250 000 satoshis → 2 500 000 unités mises à l'échelle) et que les frais de minage ne dépassent pas 10 000 satoshis (100 000 unités atomiques).
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. Liste d'autorisation d'adresses SegWit (P2WPKH) et Taproot (P2TR)
Cette règle limite les transferts de bitcoins à une adresse de destination SegWit ou Taproot approuvée.
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. Consolidation des UTXO et balayage de trésorerie
Cette règle autorise les balayages de consolidation UTXO internes, où toutes les sorties sont renvoyées vers des adresses de monnaie interne (destination_type == "TREASURY_CHANGE" et spend_amount_scaled == 0), tout en limitant les frais de consolidation.
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. Inspection de l'ensemble de sortie
Cette règle vérifie que l'ensemble de sorties de transaction contient une sortie de destination et un montant spécifiques.
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. Définition du champ d'application du réseau (Mainnet ou Testnet)
Cette règle limite l'autorisation aux transactions Bitcoin Testnet (tb), empêchant l'exécution sur 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. Ancrage des données OP_RETURN
Cette règle autorise les transactions d'ancrage de données OP_RETURN non dépensables (spend_amount_scaled == 0 et recipient == "unaddressable"), en appliquant un plafond de frais strict.
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
};
Protections de sécurité de l'analyseur syntaxique
Pour protéger les opérations de transaction dans les environnements de production, le moteur de stratégies analyse strictement les charges utiles et rejette les structures non valides au niveau de la couche de passerelle avant d'évaluer les règles Cedar :
- Application de la devise de base à valeur nulle : l'analyseur rejette explicitement les opérations de transfert de jetons Ethereum (
TOKEN_TRANSFER) qui tentent également de regrouper des éléments de transfert de base non nuls. Cela empêche les charges utiles malveillantes de transférer des valeurs d'actifs de base standards tout en présentant la transaction comme un transfert de jeton standard. - Vérification des UTXO et des témoins : pour les transactions PSBT Bitcoin, l'analyseur vérifie que toutes les entrées fournissent des données
witness_utxovalides, ce qui empêche l'usurpation du calcul des frais ou la signature non vérifiée. - Vérification du script de sortie de monnaie : les sorties de monnaie internes doivent correspondre à une clé publique de script d'entrée ou à un chemin d'accès de monnaie BIP-32 connu (
m/.../1/*). Les charges utiles qui tentent d'usurper les sorties de monnaie vers des adresses tierces échouent. - Application d'un seul destinataire externe : les charges utiles Bitcoin contenant plusieurs adresses de destination externes sans modification échouent (
ErrUnsupportedTx) pour empêcher l'autorisation ambiguë de règles multi-destinataires. - Protection contre les dépassements de capacité d'entiers positifs et négatifs : les nonces, les locktimes, les limites de gaz ou de frais, et les montants qui dépassent les limites de sécurité (
MaxInt64) ou produisent des dépassements de capacité d'entiers négatifs (par exemple, une valeur de sortie totale supérieure à la valeur d'entrée totale) sont immédiatement rejetés. - Vérification des frais manquants : les transactions qui ne définissent pas correctement les frais de minage ou les paramètres de gas échouent automatiquement.