Valutazione delle policy relative alle transazioni

Prima che il calcolo multipartitico firmi una transazione, la valuta in base alle policy di transazione nell'istanza. Questo documento descrive quali policy vengono valutate, come una policy si muove nel suo ciclo di vita, cosa può controllare una policy e perché una transazione viene rifiutata.

Come viene valutata una transazione

Una policy di transazione è una singola istruzione permit o forbid Cedar. Quando un firmatario chiama CreateTransaction, l'istanza decodifica la transazione non firmata in Transaction.payload con l'analizzatore per Transaction.schema e valuta ogni policy applicata rispetto alla transazione prima di utilizzare qualsiasi condivisione di chiavi. Una policy viene applicata quando il suo stato è ACTIVE o PENDING_DISABLED. Per saperne di più, consulta Ciclo di vita delle policy.

La decisione segue tre regole:

  1. Rifiuta per impostazione predefinita. Una transazione è consentita solo se corrisponde ad almeno una policy permit. Senza policy applicate, ogni transazione viene rifiutata.
  2. Forbid wins. Se una policy forbid corrisponde, la transazione viene negata, anche se corrispondono anche le policy permit.
  3. Una policy che non viene valutata non corrisponde. Ad esempio, una policy che legge un attributo di contesto facoltativo che la transazione non ha non viene valutata. L'istanza registra l'errore, ignora la policy e decide in base alle restanti policy applicate. Questo vale anche per le policy forbid, quindi scrivi policy forbid che non possano avere esito negativo in caso di attributo mancante. Per un esempio, consulta lo Scenario 8 e lo Scenario 9.

Una transazione che contiene più trasferimenti, ad esempio una transazione Solana con più istruzioni di trasferimento, viene valutata una volta per ogni trasferimento. La transazione è consentita solo se ogni trasferimento è consentito. Se un trasferimento viene rifiutato o non può essere decodificato, l'intera transazione viene rifiutata.

Ogni valutazione, autorizzazione o rifiuto, produce un record di valutazione che viene restituito nella transazione in Transaction.policyEvaluationRecord.

La decisione controlla se l'istanza può firmare la transazione senza attendere altri firmatari:

  • PERMIT: se la richiesta CreateTransaction contiene già un numero sufficiente di autorizzazioni dei firmatari per soddisfare la policy della chiave del keyring, la transazione passa immediatamente a SIGNING. In caso contrario, viene creata in PENDING_AUTHORIZATION e attende altri firmatari.
  • DENY: l'istanza non firma automaticamente la transazione. La transazione viene creata in PENDING_AUTHORIZATION con policyEvaluationRecord.decision impostato su DENY. I firmatari possono esaminare il record di valutazione e negare la transazione (RecordSignerDecision con DENY) o autorizzarla comunque (AUTHORIZE). La transazione viene firmata solo se un numero sufficiente di firmatari la autorizza per soddisfare la policy della chiave.

Una policy di transazione è un guardrail per la firma automatica, non un blocco per i firmatari: i firmatari possono autorizzare una transazione negata dalle policy. Il PolicyEvaluationRecord originale rimane allegato alla transazione per l'audit.

Ciclo di vita delle policy

I criteri di transazione non possono essere modificati. TransactionPolicy non ha un metodo di aggiornamento e il relativo rule è immutabile. Per modificare una regola, disattiva la policy con DisableTransactionPolicy e creane una nuova con CreateTransactionPolicy.

L'attivazione o la disattivazione di una policy richiede l'approvazione di un quorum di autori delle policy (utenti con un ruolo POLICY_AUTHOR attivo in User.roleStatuses). Ogni autore delle policy firma un TransactionPolicySigningPayload che indica la policy (o, per CreateTransactionPolicy, l'istanza), l'azione (ACTIVATE o DISABLE) e rule.cedarDocument. La richiesta che propone una modifica viene considerata come la prima approvazione. Altri autori delle policy approvano con ApproveTransactionPolicy. Il numero di approvazioni necessarie è in activationInfo.requiredApprovals e deactivationInfo.requiredApprovals. Se l'istanza richiede una sola approvazione, la modifica diventa effettiva immediatamente.

La tabella seguente descrive ogni stato delle policy e se le policy in quello stato vengono applicate:

Stato Significato Applicato?
PENDING_ACTIVE La policy è stata proposta ed è in attesa dell'approvazione dell'autore della policy. No
ACTIVE La policy ha activationInfo.requiredApprovals approvazioni. Sì
PENDING_DISABLED Un autore delle policy ha chiesto di disattivare la policy e la richiesta è in attesa di approvazione. Sì, finché la richiesta non ha deactivationInfo.requiredApprovals approvazioni
DISABLED La policy è stata disattivata o ritirata prima di diventare attiva. Le policy disattivate vengono conservate per l'audit. No

Una policy passa attraverso questi stati in una direzione:

  • Da PENDING_ACTIVE a ACTIVE: l'attivazione ha un numero sufficiente di approvazioni.
  • Da PENDING_ACTIVE a DISABLED: un autore delle policy ritira la policy con DisableTransactionPolicy prima che diventi attiva.
  • Da ACTIVE a PENDING_DISABLED: un autore delle policy chiama DisableTransactionPolicy.
  • PENDING_DISABLED a DISABLED: la richiesta di disattivazione ha un numero sufficiente di approvazioni.

Una policy entra in ogni stato In attesa al massimo una volta. Una policy disattivata non può essere riattivata. Crea invece una nuova policy.

Per sapere chi può chiamare questi metodi, consulta Ruoli utente.

Versione del set di policy

Il set di policy è l'insieme di policy applicate (ACTIVE o PENDING_DISABLED) in un determinato momento. Ogni volta che viene completata un'attivazione o una disattivazione, l'istanza assegna alla transizione il numero successivo in un contatore per l'istanza e lo registra in activationInfo.transitionSequence o deactivationInfo.transitionSequence. Questo numero è la versione del set di policy prodotta dalla transizione.

La tabella seguente mostra come cambia la versione del set di policy nel corso di una sequenza di eventi:

Evento Sequenza di transizione Policy applicate
La policy A è attivata. R: activationInfo.transitionSequence = 1 A
La policy B è attivata. B: activationInfo.transitionSequence = 2 A, B
La policy C viene proposta (PENDING_ACTIVE), poi ritirata. Nessuno A, B
Viene approvata una richiesta di disattivazione della policy A. R: deactivationInfo.transitionSequence = 3 B

Il ritiro di una policy PENDING_ACTIVE non modifica mai l'insieme di policy applicate, pertanto non viene generata alcuna sequenza di transizione e la versione dell'insieme di policy non cambia. Mentre una transizione è in attesa di approvazioni, il relativo transitionSequence non è impostato.

Ogni valutazione legge le policy, i KeyList e le chiavi a partire dalla createTime della transazione e registra la sequenza di transizione completata più alta in quel momento in policyEvaluationRecord.policySetVersion. Se due valutazioni hanno la stessa versione del set di policy, significa che hanno utilizzato le stesse policy.

La richiesta Cedar

Una richiesta Cedar ha un'entità, un'azione, una risorsa e un contesto. Ad esempio:

permit (
  principal == User::"alice@example.com",
  action == Action::"buy_transaction",
  resource == Resource::"transaction_management"
)
when {
  context.principal_keyring == "institutional-treasury" &&
  context has fiat_amount && context.fiat_amount <= 10000
};

Come un utente viene mappato al principal Cedar

L'entità è l'iniziatore della transazione: l'utente il cui principal corrisponde all'identità autenticata del chiamante di CreateTransaction. L'utente deve avere un ruolo SIGNER attivo. In Cedar, l'entità è un'entità User il cui ID è il campo principal dell'utente, ad esempio User::"alice@example.com".

L'istanza non trasmette dati delle entità a Cedar. Un'entità User non ha attributi né elementi principali, pertanto:

  • principal == User::"alice@example.com" corrisponde alle transazioni avviate da Alice.
  • principal in Team::"treasury" non corrisponde mai. Per limitare chi può firmare con una chiave, utilizza la policy della chiave del keyring. Per applicare una regola a un gruppo di chiavi, seleziona context.principal_keyring.
  • Una regola che legge un attributo di principal, ad esempio principal.team, non viene valutata.

L'indirizzo principal di un utente non può essere modificato, quindi una regola che nomina un'entità continua a fare riferimento alla stessa identità.

Azione e risorsa

  • action: il valore di Transaction.action nella richiesta CreateTransaction, formattato come entità Cedar Action. CreateTransaction accetta le seguenti azioni:

    Azione Utilizzato per
    Action::"buy_transaction" Una transazione che acquisisce un asset.
    Action::"sell_transaction" Una transazione che elimina un asset.
    Action::"internal_transfer_transaction" Un trasferimento di un asset, ad esempio un pagamento o uno sweep tra chiavi.

    Chi avvia la richiesta sceglie l'azione; il calcolo multipartitico non la deduce dal payload. Una regola può corrispondere a un'azione (action == Action::"buy_transaction"), a un elenco di azioni (action in [Action::"buy_transaction", Action::"sell_transaction"]) oppure lasciare action senza vincoli per corrispondere a ogni azione.

  • resource: sempre Resource::"transaction_management" per le valutazioni delle transazioni. Una regola può controllare resource == Resource::"transaction_management" o lasciare resource senza vincoli.

Attributi di contesto

Il contesto contiene gli attributi controllati dalle policy. Provengono da due fonti:

  • Il payload della transazione e la chiave di firma. L'istanza decodifica Transaction.payload e aggiunge gli ID della chiave di firma e del relativo keyring. Questi attributi sono principal_keyring, principal_key, blockchain, schema, secondary_key, amount_token_scaled, token_symbol, contract_address, chain_id, max_fee_atomic, payload e time_stamp. Per la tabella completa e il comportamento di ogni blockchain, consulta Scrivi le regole delle policy di transazione.
  • Il campo metadata della transazione,che l'iniziatore imposta in CreateTransaction.

La tabella seguente descrive gli attributi dei metadati:

Campo Transaction.metadata Attributo Cedar Tipo di cedro Valore
fiatAmount context.fiat_amount Long Il valore della transazione in dollari statunitensi interi (google.type.Money). currencyCode deve essere USD, units deve essere maggiore o uguale a zero e nanos deve essere 0.
validity context.validity Long La durata della validità della transazione (google.protobuf.Duration), in secondi interi. Deve essere maggiore di 0 secondi, senza frazioni di secondo.
principalValue1 context.principal_value1 String Qualsiasi valore definito, fino a 256 caratteri, ad esempio un trading desk o un centro di costo.
principalValue2 context.principal_value2 String Qualsiasi valore definito, fino a 256 caratteri, ad esempio un ticket interno o un ID controparte.

Ai metadati si applicano le seguenti regole:

  • I campi non impostati non sono presenti nel contesto. Se una transazione non ha fiatAmount, context.fiat_amount non esiste e una policy che la legge non riesce a valutarla. Controlla prima l'attributo con has, come in context has fiat_amount && context.fiat_amount <= 10000.
  • I metadati non validi causano l'errore della richiesta. Se un campo viola le regole della tabella precedente, ad esempio un fiatAmount in EUR o con nanos diverso da zero, un validity di 0 secondi o un principalValue1 più lungo di 256 caratteri, CreateTransaction non va a buon fine con INVALID_ARGUMENT e non viene valutata alcuna policy.
  • L'istanza non controlla i metadati rispetto alla transazione. fiatAmount è il valore della transazione secondo l'iniziatore. Gli altri firmatari vedono i metadati in Transaction.metadata e policyEvaluationRecord.evaluationContext prima di autorizzarli. Per limitare gli importi on-chain indipendentemente dai metadati, controlla context.amount_token_scaled e context.contract_address.
  • I metadati non possono essere modificati dopo la creazione della transazione.

KeyRing

Un KeyRing raggruppa le chiavi. Il contesto di ogni transazione ha principal_keyring e principal_key, quindi una regola può essere applicata a ogni chiave in un KeyRing, incluse le chiavi create in un secondo momento, e un KeyRing può essere una voce in un KeyList. Per saperne di più e per un esempio di regola, consulta KeyRings.

KeyLists

Un KeyList è un elenco denominato di indirizzi blockchain a cui le policy possono fare riferimento, ad esempio come lista consentita di destinazioni. Ogni voce è una delle seguenti:

  • Una voce manuale (manualEntry): un indirizzo non gestito dall'istanza, con campi source e reason facoltativi.
  • Una chiave nell'istanza (key): corrisponde agli indirizzi della chiave.
  • Un KeyRing nell'istanza (keyRing): corrisponde agli indirizzi di ogni chiave attiva nel KeyRing, incluse le chiavi create dopo l'aggiunta della voce.

Gli elenchi di chiavi possono cambiare dopo l'approvazione di una policy. Quando aggiungi o rimuovi una voce con AddKeyListEntries o RemoveKeyListEntries, ogni policy che fa riferimento a KeyList utilizza le nuove voci della valutazione successiva, senza nuove approvazioni dell'autore della policy. Un KeyList non può essere eliminato con DeleteKeyList mentre una policy PENDING_ACTIVE, ACTIVE o PENDING_DISABLED vi fa riferimento.

KeyList nel contesto di Cedar

Al momento della valutazione, l'istanza espande ogni KeyList in un Set di indirizzi blockchain String: le voci manuali, più gli indirizzi derivati da ogni voce di chiave e KeyRing. Ogni set viene passato a Cedar come context.key_lists["<var>KEY_LIST_ID</var>"], dove KEY_LIST_ID è l'ID {keyList} nel nome della risorsa di KeyList, ad esempio trusted-destinations per projects/my-project/locations/us-central1/instances/my-instance/keyLists/trusted-destinations.

Una regola verifica l'appartenenza con l'operatore Cedar contains rispetto all'indirizzo di destinazione decodificato, context.secondary_key. Ad esempio, per consentire i trasferimenti solo agli indirizzi nell'elenco di chiavi trusted-destinations:

// Assuming you created a KeyList with ID "trusted-destinations":
permit (principal, action, resource)
when { context.key_lists["trusted-destinations"].contains(context.secondary_key) };

Per negare i trasferimenti a qualsiasi indirizzo nell'elenco di chiavi blocked-addresses:

// Assuming you created a KeyList with ID "blocked-addresses":
forbid (principal, action, resource)
when { context.key_lists["blocked-addresses"].contains(context.secondary_key) };

Tieni presente che:

  • Utilizza la sintassi tra parentesi, non la sintassi con punto, per l'ID KeyList. La sintassi con punto di Cedar (context.key_lists.trusted-destinations) non riesce ad analizzare quando l'ID contiene un trattino, che Cedar legge come sottrazione, o inizia con una cifra, come può fare un UUID generato dal server. La sintassi tra parentesi, context.key_lists["<var>KEY_LIST_ID</var>"], funziona per ogni ID.
  • key_lists è sempre presente e una regola può leggere direttamente un KeyList al suo interno. CreateTransactionPolicy verifica che ogni KeyList a cui fa riferimento la regola esista e DeleteKeyList rifiuta di eliminare una KeyList se una policy vi fa riferimento. Utilizza context.key_lists has "<var>KEY_LIST_ID</var>" solo quando una regola fa riferimento a un KeyList che potrebbe non esistere ancora.
  • Gli indirizzi vengono confrontati come stringhe. secondary_key utilizza il formato descritto in Scrivi regole della policy per le transazioni per ogni blockchain, ad esempio il formato di checksum EIP-55 con lettere maiuscole e minuscole per Ethereum. Aggiungi voci manuali nello stesso formato.
  • Il campo secondary_key di un trasferimento di token Solana è l'account del token di destinazione, non il wallet del proprietario. Per consentire un wallet, aggiungi il relativo account token per ogni mint che consenti.

Ogni valutazione risolve l'appartenenza a KeyList in base al createTime della transazione, nello stesso momento delle policy, e registra il risultato in policyEvaluationRecord.keyListMemberships: KeyList, l'indirizzo testato, se era un membro e la voce corrispondente.

Poiché un KeyList modifica ciò che un criterio consente, limita chi può modificarlo. I metodi KeyList richiedono roles/mpc.admin. Per saperne di più, consulta Autorizzazioni IAM.

Motivi del rifiuto

Quando policyEvaluationRecord.decision è DENY, policyEvaluationRecord.denyReason spiega il motivo. La tabella seguente descrive ogni motivo di rifiuto:

Motivo rifiuto Quando Determinazione delle policy
FORBID_RULE_MATCHED È stata trovata almeno una corrispondenza con una policy forbid applicata. Le forbid policy corrispondenti.
NO_PERMIT_RULE_MATCHED Il payload è stato decodificato, nessuna policy forbid è stata trovata, nessuna policy non è stata valutata e nessuna policy permit è stata trovata. Nessuno
EVALUATION_ERROR Nessuna policy permit o forbid corrisponde e la valutazione di almeno una policy non è riuscita, ad esempio perché legge un attributo facoltativo che non è presente nel contesto. Nessuno. evaluationErrors elenca gli errori.
UNRECOGNIZED_PAYLOAD L'istanza non è riuscita a decodificare Transaction.payload o a proiettarlo in un contesto, ad esempio a causa di byte non corretti, un'istruzione o un'operazione di contratto non supportata o una transazione Bitcoin con più destinatari. Nessuna policy viene valutata. Nessuno. evaluationErrors elenca l'errore del parser.

I motivi vengono decisi nel seguente ordine:

  1. Se il payload non può essere decodificato o proiettato in un contesto, la decisione è DENY con UNRECOGNIZED_PAYLOAD.
  2. In caso contrario, viene valutata ogni policy applicata. Se una policy forbid corrisponde, la decisione è DENY con FORBID_RULE_MATCHED, anche se corrispondono anche le policy permit o se la valutazione di altre policy non è riuscita.
  3. In caso contrario, se almeno una policy permit corrisponde, la decisione è PERMIT. Gli errori di altre policy vengono comunque registrati in evaluationErrors.
  4. In caso contrario, la decisione è DENY con EVALUATION_ERROR se la valutazione di una policy non è riuscita o NO_PERMIT_RULE_MATCHED se la valutazione di ogni policy è stata eseguita senza corrispondenza.

Gli errori vengono registrati anche quando la decisione è PERMIT, quindi controlla il record di valutazione per verificare se esistono policy che non corrispondono mai perché non vanno mai a buon fine.

Scenari

Negli scenari da 1 a 9, Alice (User::"alice@example.com") crea un trasferimento Ethereum valido con action impostato su Action::"internal_transfer_transaction" e questi metadati, a meno che lo scenario non indichi diversamente:

"metadata": {
  "fiatAmount": {"currencyCode": "USD", "units": "5000"},
  "principalValue1": "treasury-desk"
}

La transazione non ha validity né principalValue2.

La tabella seguente riassume ogni scenario:

Scenario Norme relative all'applicazione delle norme o payload Decisione Motivo rifiuto
1 Nessuno DENY NO_PERMIT_RULE_MATCHED
2 Un permit corrispondente PERMIT
3 Un permit che non corrisponde DENY NO_PERMIT_RULE_MATCHED
4 Due permit, una corrispondenza PERMIT
5 Un permit e un forbid che corrispondono entrambi DENY FORBID_RULE_MATCHED
6 Un permit che legge un attributo mancante DENY EVALUATION_ERROR
7 Sempre permit, con has DENY NO_PERMIT_RULE_MATCHED
8 Un forbid che legge un attributo mancante e un permit corrispondente PERMIT
9 Un forbid che richiede un attributo DENY FORBID_RULE_MATCHED
10 Un payload che non può essere decodificato DENY UNRECOGNIZED_PAYLOAD

Scenario 1: nessuna policy applicata

L'istanza non ha policy ACTIVE o PENDING_DISABLED.

Decisione: DENY, NO_PERMIT_RULE_MATCHED. Senza una policy permit corrispondente, ogni transazione viene rifiutata. In una nuova istanza, nessuna transazione viene firmata automaticamente finché gli autori delle policy non attivano una policy permit; i firmatari devono autorizzare ogni transazione.

Scenario 2: un permesso corrispondente

permit (principal, action, resource)
when { context has fiat_amount && context.fiat_amount <= 10000 };

Decisione: PERMIT. L'importo, 5000, è al massimo 10.000. determiningPolicyIds elenca questa policy.

Scenario 3: un permesso non corrispondente

permit (principal, action, resource)
when { context has fiat_amount && context.fiat_amount <= 1000 };

Decisione: DENY, NO_PERMIT_RULE_MATCHED. L'importo, 5000, è superiore a 1000 e nessun'altra policy consente la transazione.

Scenario 4: due permessi, uno corrisponde

Policy A:

permit (principal, action, resource)
when { context has fiat_amount && context.fiat_amount <= 1000 };

Policy B:

permit (
  principal == User::"alice@example.com",
  action == Action::"internal_transfer_transaction",
  resource == Resource::"transaction_management"
)
when {
  context has fiat_amount && context.fiat_amount <= 25000 &&
  context has principal_value1 && context.principal_value1 == "treasury-desk"
};

Decisione: PERMIT. La policy A non corrisponde, ma la policy B sì. È sufficiente una policy permit corrispondente. determiningPolicyIds elenca solo la Policy B.

Scenario 5: un'istruzione Forbid esegue l'override di un'istruzione Permit

Policy A:

permit (principal, action, resource)
when { context has fiat_amount && context.fiat_amount <= 10000 };

Policy B:

forbid (principal, action, resource)
when { context has principal_value1 && context.principal_value1 == "treasury-desk" };

Decisione: DENY, FORBID_RULE_MATCHED. Entrambe le policy corrispondono e forbid vince. determiningPolicyIds elenca solo la Policy B.

Scenario 6: un permesso legge un attributo mancante

permit (principal, action, resource)
when { context.validity <= 3600 };

Decisione: DENY, EVALUATION_ERROR. La transazione non ha validity, quindi context.validity non esiste e la policy non viene valutata. Nessun'altra policy consente la transazione. evaluationErrors elenca l'errore.

Scenario 7: lo stesso permesso, con

permit (principal, action, resource)
when { context has validity && context.validity <= 3600 };

Decisione: DENY, NO_PERMIT_RULE_MATCHED. context has validity è false, quindi la policy restituisce false anziché non riuscire. La transazione viene comunque negata, ma il motivo mostra che la policy è stata valutata e non corrisponde.

Scenario 8: un'istruzione Forbid legge un attributo mancante

Policy A:

permit (principal, action, resource)
when { context has fiat_amount && context.fiat_amount <= 10000 };

Policy B:

forbid (principal, action, resource)
when { context.principal_value2 == "sanctioned-counterparty" };

Decisione: PERMIT. La transazione non ha principalValue2, quindi la policy B non viene valutata e viene saltata. La norma A corrisponde. determiningPolicyIds elenca la policy A e evaluationErrors elenca l'errore della policy B.

Scenario 9: un divieto che richiede un attributo

La policy A è la policy permit dello scenario 8. Policy B:

forbid (principal, action, resource)
unless { context has fiat_amount };

Decisione: PERMIT per la transazione in questi scenari, che ha un fiatAmount. Se Alice omette fiatAmount, la decisione è DENY, FORBID_RULE_MATCHED: context has fiat_amount è false, quindi la policy forbid corrisponde. La valutazione di questa policy non può non riuscire, perché utilizza solo has.

Per combinare un attributo obbligatorio con un controllo del suo valore in un'unica policy forbid, controlla prima l'attributo:

forbid (principal, action, resource)
unless { context has fiat_amount && context.fiat_amount <= 10000 };

Scenario 10: un payload che non può essere decodificato

Alice crea una transazione i cui payload non possono essere decodificati dall'analizzatore per Transaction.schema, ad esempio byte RLP troncati, un PSBT Bitcoin con diversi destinatari o una transazione Solana con un'istruzione non supportata.

Decisione: DENY, UNRECOGNIZED_PAYLOAD. Nessuna policy viene valutata. evaluationErrors elenca l'errore del parser e determiningPolicyIds è vuoto.

Record di valutazione

Ogni valutazione produce un PolicyEvaluationRecord che non può essere modificato. Viene restituito in Transaction.policyEvaluationRecord e contiene i seguenti campi:

Campo Valore
decision PERMIT o DENY.
denyReason Uno dei motivi del rifiuto. Non impostato quando la decisione è PERMIT.
determiningPolicyIds Il giorno PERMIT, gli ID delle policy permit corrispondenti. Il giorno FORBID_RULE_MATCHED, gli ID delle policy forbid corrispondenti. In caso contrario, è vuoto.
evaluationErrors Gli errori delle policy che non sono state valutate o l'errore dell'analizzatore quando denyReason è UNRECOGNIZED_PAYLOAD.
evaluationContext Il contesto Cedar in base al quale sono state valutate le policy, come google.protobuf.Struct. I numeri interi a 64 bit vengono archiviati come stringhe decimali per mantenerne la precisione.
policySetVersion La versione del set di policy utilizzata dalla valutazione.
keyListMemberships Le iscrizioni a KeyList risolte durante la valutazione.
intentDigest Il digest con codifica esadecimale in minuscolo del payload della transazione valutata. L'hash dipende dallo schema del payload: Keccak-256 della transazione per ETHEREUM_TX_V2, il sighash del primo input per BITCOIN_TX_V2, SHA-256 del messaggio non firmato per SOLANA_TX_V1 e il digest di firma EIP-712, keccak256(0x1901 ++ domainSeparator ++ hashStruct(message)), per EIP712_TYPED_DATA_V1.
evaluationTime Quando è stata eseguita la valutazione.