From 23e207623d5c6ed321357d1007b1c25804fd8273 Mon Sep 17 00:00:00 2001 From: Gustavo Inacio Date: Thu, 23 Jan 2025 15:01:20 +0100 Subject: [PATCH 1/3] refactor!: remove unused escrow handler methods Signed-off-by: Gustavo Inacio --- tap_core/src/manager/adapters/escrow.rs | 53 ++---------------- tap_core/src/manager/context/memory.rs | 10 ---- tap_core/src/manager/tap_manager.rs | 24 +++----- tap_core/src/rav/request.rs | 4 +- tap_core/src/receipt/received_receipt.rs | 33 +---------- tap_core/src/receipt/state.rs | 10 +--- tap_core/tests/escrow_test.rs | 70 ------------------------ tap_core/tests/received_receipt_test.rs | 33 ++--------- 8 files changed, 25 insertions(+), 212 deletions(-) delete mode 100644 tap_core/tests/escrow_test.rs diff --git a/tap_core/src/manager/adapters/escrow.rs b/tap_core/src/manager/adapters/escrow.rs index 6570c513..213e39d2 100644 --- a/tap_core/src/manager/adapters/escrow.rs +++ b/tap_core/src/manager/adapters/escrow.rs @@ -1,14 +1,10 @@ // Copyright 2023-, Semiotic AI, Inc. // SPDX-License-Identifier: Apache-2.0 -use alloy::{dyn_abi::Eip712Domain, primitives::Address}; +use alloy::{dyn_abi::Eip712Domain, primitives::Address, sol_types::SolStruct}; use async_trait::async_trait; -use crate::{ - rav::SignedRAV, - receipt::{state::AwaitingReserve, ReceiptError, ReceiptResult, ReceiptWithState}, - Error, -}; +use crate::{signed_message::EIP712SignedMessage, Error}; /// Manages the escrow operations /// @@ -25,53 +21,16 @@ pub trait EscrowHandler: Send + Sync { /// Errors of this type are returned to the user when an operation fails. type AdapterError: std::error::Error + std::fmt::Debug + Send + Sync + 'static; - /// Retrieves the local accounting amount of available escrow for a specified sender. - async fn get_available_escrow(&self, sender_id: Address) -> Result; - - /// Deducts a specified value from the local accounting of available escrow for a specified sender. - async fn subtract_escrow( - &self, - sender_id: Address, - value: u128, - ) -> Result<(), Self::AdapterError>; - /// Verifies the signer of the receipt - /// - /// Used by [`Self::check_rav_signature`] to verify the signer of the receipt async fn verify_signer(&self, signer_address: Address) -> Result; - /// Checks and reserves escrow for the received receipt - async fn check_and_reserve_escrow( - &self, - received_receipt: &ReceiptWithState, - domain_separator: &Eip712Domain, - ) -> ReceiptResult<()> { - let signed_receipt = &received_receipt.signed_receipt; - let receipt_signer_address = - signed_receipt - .recover_signer(domain_separator) - .map_err(|err| ReceiptError::InvalidSignature { - source_error_message: err.to_string(), - })?; - - if self - .subtract_escrow(receipt_signer_address, signed_receipt.message.value) - .await - .is_err() - { - return Err(ReceiptError::SubtractEscrowFailed); - } - - Ok(()) - } - - /// Checks the signature of the RAV - async fn check_rav_signature( + /// Checks if the signed message has a sender signature + async fn check_signature( &self, - signed_rav: &SignedRAV, + signed_message: &EIP712SignedMessage, domain_separator: &Eip712Domain, ) -> Result<(), Error> { - let recovered_address = signed_rav.recover_signer(domain_separator)?; + let recovered_address = signed_message.recover_signer(domain_separator)?; if self .verify_signer(recovered_address) .await diff --git a/tap_core/src/manager/context/memory.rs b/tap_core/src/manager/context/memory.rs index 455b123d..3385fc8a 100644 --- a/tap_core/src/manager/context/memory.rs +++ b/tap_core/src/manager/context/memory.rs @@ -243,16 +243,6 @@ impl InMemoryContext { #[async_trait] impl EscrowHandler for InMemoryContext { type AdapterError = InMemoryError; - async fn get_available_escrow(&self, sender_id: Address) -> Result { - self.escrow(sender_id) - } - async fn subtract_escrow( - &self, - sender_id: Address, - value: u128, - ) -> Result<(), Self::AdapterError> { - self.reduce_escrow(sender_id, value) - } async fn verify_signer(&self, signer_address: Address) -> Result { Ok(self diff --git a/tap_core/src/manager/tap_manager.rs b/tap_core/src/manager/tap_manager.rs index 304e4d17..2f943222 100644 --- a/tap_core/src/manager/tap_manager.rs +++ b/tap_core/src/manager/tap_manager.rs @@ -8,7 +8,7 @@ use crate::{ rav::{RAVRequest, ReceiptAggregateVoucher, SignedRAV}, receipt::{ checks::{CheckBatch, CheckList, TimestampCheck, UniqueCheck}, - state::{Failed, Reserved}, + state::{Checked, Failed}, Context, ReceiptError, ReceiptWithState, SignedReceipt, }, Error, @@ -56,7 +56,7 @@ where signed_rav: SignedRAV, ) -> std::result::Result<(), Error> { self.context - .check_rav_signature(&signed_rav, &self.domain_separator) + .check_signature(&signed_rav, &self.domain_separator) .await?; if signed_rav.message != expected_rav { @@ -105,7 +105,7 @@ where limit: Option, ) -> Result< ( - Vec>, + Vec>, Vec>, ), Error, @@ -126,9 +126,8 @@ where source_error: anyhow::Error::new(err), })?; - let mut awaiting_reserve_receipts = vec![]; + let mut checked_receipts = vec![]; let mut failed_receipts = vec![]; - let mut reserved_receipts = vec![]; // check for timestamp let (checking_receipts, already_failed) = @@ -146,21 +145,12 @@ where .map_err(|e| Error::ReceiptError(ReceiptError::RetryableCheck(e)))?; match receipt { - Ok(checked) => awaiting_reserve_receipts.push(checked), - Err(failed) => failed_receipts.push(failed), - } - } - for checked in awaiting_reserve_receipts { - match checked - .check_and_reserve_escrow(&self.context, &self.domain_separator) - .await - { - Ok(reserved) => reserved_receipts.push(reserved), + Ok(checked) => checked_receipts.push(checked), Err(failed) => failed_receipts.push(failed), } } - Ok((reserved_receipts, failed_receipts)) + Ok((checked_receipts, failed_receipts)) } } @@ -210,7 +200,7 @@ where } fn generate_expected_rav( - receipts: &[ReceiptWithState], + receipts: &[ReceiptWithState], previous_rav: Option, ) -> Result { if receipts.is_empty() { diff --git a/tap_core/src/rav/request.rs b/tap_core/src/rav/request.rs index 3854d7f2..f58fa14e 100644 --- a/tap_core/src/rav/request.rs +++ b/tap_core/src/rav/request.rs @@ -4,7 +4,7 @@ use crate::{ rav::{ReceiptAggregateVoucher, SignedRAV}, receipt::{ - state::{Failed, Reserved}, + state::{Failed, Checked}, ReceiptWithState, }, Error, @@ -14,7 +14,7 @@ use crate::{ #[derive(Debug)] pub struct RAVRequest { /// List of checked and reserved receipts to aggregate - pub valid_receipts: Vec>, + pub valid_receipts: Vec>, /// Optional previous RAV to aggregate with pub previous_rav: Option, /// List of failed receipt used to log invalid receipts diff --git a/tap_core/src/receipt/received_receipt.rs b/tap_core/src/receipt/received_receipt.rs index 708d6dab..119d1a89 100644 --- a/tap_core/src/receipt/received_receipt.rs +++ b/tap_core/src/receipt/received_receipt.rs @@ -13,14 +13,11 @@ //! This module is useful for managing and tracking the state of received receipts, as well as //! their progress through various checks and stages of inclusion in RAV requests and received RAVs. -use alloy::dyn_abi::Eip712Domain; - use super::{checks::CheckError, Context, Receipt, ReceiptError, ReceiptResult, SignedReceipt}; use crate::{ - manager::adapters::EscrowHandler, receipt::{ checks::ReceiptCheck, - state::{AwaitingReserve, Checking, Failed, ReceiptState, Reserved}, + state::{Checked, Checking, Failed, ReceiptState}, }, signed_message::EIP712SignedMessage, }; @@ -50,30 +47,6 @@ where pub(crate) _state: S, } -impl ReceiptWithState { - /// Perform the checks implemented by the context and reserve escrow if - /// all checks pass - /// - /// Returns a [`ReceiptWithState`] if successful, otherwise - /// returns a [`ReceiptWithState`] - pub async fn check_and_reserve_escrow( - self, - context: &E, - domain_separator: &Eip712Domain, - ) -> ResultReceipt - where - E: EscrowHandler, - { - match context - .check_and_reserve_escrow(&self, domain_separator) - .await - { - Ok(_) => Ok(self.perform_state_changes(Reserved)), - Err(e) => Err(self.perform_state_error(e)), - } - } -} - impl ReceiptWithState { /// Creates a new `ReceiptWithState` in the `Checking` state pub fn new(signed_receipt: SignedReceipt) -> ReceiptWithState { @@ -115,14 +88,14 @@ impl ReceiptWithState { mut self, ctx: &Context, checks: &[ReceiptCheck], - ) -> Result, String> { + ) -> Result, String> { let all_checks_passed = self.perform_checks(ctx, checks).await; if let Err(ReceiptError::RetryableCheck(e)) = all_checks_passed { Err(e.to_string()) } else if let Err(e) = all_checks_passed { Ok(Err(self.perform_state_error(e))) } else { - let checked = self.perform_state_changes(AwaitingReserve); + let checked = self.perform_state_changes(Checked); Ok(Ok(checked)) } } diff --git a/tap_core/src/receipt/state.rs b/tap_core/src/receipt/state.rs index 38e7e08b..78f1f3de 100644 --- a/tap_core/src/receipt/state.rs +++ b/tap_core/src/receipt/state.rs @@ -21,18 +21,12 @@ pub struct Failed { pub error: ReceiptError, } -/// AwaitingReserve state represents a receipt that has passed all checks -/// and is awaiting escrow reservation. -#[derive(Debug, Clone)] -pub struct AwaitingReserve; - /// Reserved state represents a receipt that has successfully reserved escrow. #[derive(Debug, Clone)] -pub struct Reserved; +pub struct Checked; /// Trait for the different states a receipt can be in. pub trait ReceiptState {} impl ReceiptState for Checking {} -impl ReceiptState for AwaitingReserve {} -impl ReceiptState for Reserved {} +impl ReceiptState for Checked {} impl ReceiptState for Failed {} diff --git a/tap_core/tests/escrow_test.rs b/tap_core/tests/escrow_test.rs deleted file mode 100644 index 1b4b5bfb..00000000 --- a/tap_core/tests/escrow_test.rs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2023-, Semiotic AI, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use std::{ - collections::HashMap, - sync::{Arc, RwLock}, -}; - -use alloy::signers::local::PrivateKeySigner; -use rstest::*; -use tap_core::{ - manager::{adapters::EscrowHandler, context::memory::InMemoryContext}, - receipt::checks::StatefulTimestampCheck, -}; - -#[fixture] -fn context() -> InMemoryContext { - let escrow_storage = Arc::new(RwLock::new(HashMap::new())); - let rav_storage = Arc::new(RwLock::new(None)); - let receipt_storage = Arc::new(RwLock::new(HashMap::new())); - - let timestamp_check = Arc::new(StatefulTimestampCheck::new(0)); - InMemoryContext::new( - rav_storage, - receipt_storage.clone(), - escrow_storage.clone(), - timestamp_check, - ) -} - -#[rstest] -#[tokio::test] -async fn escrow_handler_test(mut context: InMemoryContext) { - let wallet = PrivateKeySigner::random(); - let sender_id = wallet.address(); - - let invalid_wallet = PrivateKeySigner::random(); - let invalid_sender_id = invalid_wallet.address(); - - let initial_value = 500u128; - - context.increase_escrow(sender_id, initial_value); - - // Check that sender exists and has valid value through adapter - assert!(context.get_available_escrow(sender_id).await.is_ok()); - assert_eq!( - context.get_available_escrow(sender_id).await.unwrap(), - initial_value - ); - - // Check that subtracting is valid for valid sender, and results in expected value - assert!(context - .subtract_escrow(sender_id, initial_value) - .await - .is_ok()); - assert!(context.get_available_escrow(sender_id).await.is_ok()); - assert_eq!(context.get_available_escrow(sender_id).await.unwrap(), 0); - - // Check that subtracting to negative escrow results in err - assert!(context - .subtract_escrow(sender_id, initial_value) - .await - .is_err()); - - // Check that accessing non initialized sender results in err - assert!(context - .get_available_escrow(invalid_sender_id) - .await - .is_err()); -} diff --git a/tap_core/tests/received_receipt_test.rs b/tap_core/tests/received_receipt_test.rs index 2b6c6e0b..bb0fc743 100644 --- a/tap_core/tests/received_receipt_test.rs +++ b/tap_core/tests/received_receipt_test.rs @@ -10,9 +10,7 @@ use std::{ use alloy::{dyn_abi::Eip712Domain, primitives::Address, signers::local::PrivateKeySigner}; use rstest::*; use tap_core::{ - manager::context::memory::{ - checks::get_full_list_of_checks, EscrowStorage, InMemoryContext, QueryAppraisals, - }, + manager::context::memory::{checks::get_full_list_of_checks, EscrowStorage, QueryAppraisals}, receipt::{ checks::{ReceiptCheck, StatefulTimestampCheck}, Context, Receipt, ReceiptWithState, @@ -56,7 +54,6 @@ fn domain_separator() -> Eip712Domain { } struct ContextFixture { - context: InMemoryContext, escrow_storage: EscrowStorage, query_appraisals: QueryAppraisals, checks: Vec, @@ -71,18 +68,9 @@ fn context( ) -> ContextFixture { let (signer, sender_ids) = sender_ids; let escrow_storage = Arc::new(RwLock::new(HashMap::new())); - let rav_storage = Arc::new(RwLock::new(None)); - let receipt_storage = Arc::new(RwLock::new(HashMap::new())); let query_appraisals = Arc::new(RwLock::new(HashMap::new())); let timestamp_check = Arc::new(StatefulTimestampCheck::new(0)); - let context = InMemoryContext::new( - rav_storage, - receipt_storage.clone(), - escrow_storage.clone(), - timestamp_check.clone(), - ) - .with_sender_address(signer.address()); let mut checks = get_full_list_of_checks( domain_separator, sender_ids.iter().cloned().collect(), @@ -93,7 +81,6 @@ fn context( ContextFixture { signer, - context, escrow_storage, query_appraisals, checks, @@ -153,7 +140,6 @@ async fn partial_then_finalize_valid_receipt( ) { let ContextFixture { checks, - context, escrow_storage, query_appraisals, signer, @@ -187,12 +173,8 @@ async fn partial_then_finalize_valid_receipt( .await; assert!(awaiting_escrow_receipt.is_ok()); - let awaiting_escrow_receipt = awaiting_escrow_receipt.unwrap(); - let receipt = awaiting_escrow_receipt - .unwrap() - .check_and_reserve_escrow(&context, &domain_separator) - .await; - assert!(receipt.is_ok()); + let checked_receipt = awaiting_escrow_receipt.unwrap(); + assert!(checked_receipt.is_ok()); } #[rstest] @@ -204,7 +186,6 @@ async fn standard_lifetime_valid_receipt( ) { let ContextFixture { checks, - context, escrow_storage, query_appraisals, signer, @@ -239,10 +220,6 @@ async fn standard_lifetime_valid_receipt( .await; assert!(awaiting_escrow_receipt.is_ok()); - let awaiting_escrow_receipt = awaiting_escrow_receipt.unwrap(); - let receipt = awaiting_escrow_receipt - .unwrap() - .check_and_reserve_escrow(&context, &domain_separator) - .await; - assert!(receipt.is_ok()); + let checked_receipt = awaiting_escrow_receipt.unwrap(); + assert!(checked_receipt.is_ok()); } From fcc64b01451f5fd962fee244aa116d81c779a500 Mon Sep 17 00:00:00 2001 From: Gustavo Inacio Date: Thu, 23 Jan 2025 15:01:38 +0100 Subject: [PATCH 2/3] refactor: rename escrow handler to signature checker Signed-off-by: Gustavo Inacio --- tap_core/src/manager/adapters/mod.rs | 4 ++-- tap_core/src/manager/adapters/{escrow.rs => signature.rs} | 2 +- tap_core/src/manager/context/memory.rs | 2 +- tap_core/src/manager/tap_manager.rs | 8 ++++---- tap_integration_tests/tests/indexer_mock.rs | 8 ++++---- 5 files changed, 12 insertions(+), 12 deletions(-) rename tap_core/src/manager/adapters/{escrow.rs => signature.rs} (97%) diff --git a/tap_core/src/manager/adapters/mod.rs b/tap_core/src/manager/adapters/mod.rs index 8ba2a9a0..ca3395c5 100644 --- a/tap_core/src/manager/adapters/mod.rs +++ b/tap_core/src/manager/adapters/mod.rs @@ -8,10 +8,10 @@ //! allows for easy integration with various storage solutions and verification //! procedures, thereby making the library adaptable to a wide range of use cases. -mod escrow; +mod signature; mod rav; mod receipt; -pub use escrow::EscrowHandler; +pub use signature::SignatureChecker; pub use rav::*; pub use receipt::*; diff --git a/tap_core/src/manager/adapters/escrow.rs b/tap_core/src/manager/adapters/signature.rs similarity index 97% rename from tap_core/src/manager/adapters/escrow.rs rename to tap_core/src/manager/adapters/signature.rs index 213e39d2..ffb34ae3 100644 --- a/tap_core/src/manager/adapters/escrow.rs +++ b/tap_core/src/manager/adapters/signature.rs @@ -13,7 +13,7 @@ use crate::{signed_message::EIP712SignedMessage, Error}; /// For example code see [crate::manager::context::memory::EscrowStorage] #[async_trait] -pub trait EscrowHandler: Send + Sync { +pub trait SignatureChecker: Send + Sync { /// Defines the user-specified error type. /// /// This error type should implement the `Error` and `Debug` traits from diff --git a/tap_core/src/manager/context/memory.rs b/tap_core/src/manager/context/memory.rs index 3385fc8a..4882fe66 100644 --- a/tap_core/src/manager/context/memory.rs +++ b/tap_core/src/manager/context/memory.rs @@ -241,7 +241,7 @@ impl InMemoryContext { } #[async_trait] -impl EscrowHandler for InMemoryContext { +impl SignatureChecker for InMemoryContext { type AdapterError = InMemoryError; async fn verify_signer(&self, signer_address: Address) -> Result { diff --git a/tap_core/src/manager/tap_manager.rs b/tap_core/src/manager/tap_manager.rs index 2f943222..4ecd1279 100644 --- a/tap_core/src/manager/tap_manager.rs +++ b/tap_core/src/manager/tap_manager.rs @@ -3,7 +3,7 @@ use alloy::dyn_abi::Eip712Domain; -use super::adapters::{EscrowHandler, RAVRead, RAVStore, ReceiptDelete, ReceiptRead, ReceiptStore}; +use super::adapters::{SignatureChecker, RAVRead, RAVStore, ReceiptDelete, ReceiptRead, ReceiptStore}; use crate::{ rav::{RAVRequest, ReceiptAggregateVoucher, SignedRAV}, receipt::{ @@ -42,7 +42,7 @@ impl Manager { impl Manager where - E: RAVStore + EscrowHandler, + E: RAVStore + SignatureChecker, { /// Verify `signed_rav` matches all values on `expected_rav`, and that `signed_rav` has a valid signer. /// @@ -95,7 +95,7 @@ where impl Manager where - E: ReceiptRead + EscrowHandler, + E: ReceiptRead + SignatureChecker, { async fn collect_receipts( &self, @@ -156,7 +156,7 @@ where impl Manager where - E: ReceiptRead + RAVRead + EscrowHandler, + E: ReceiptRead + RAVRead + SignatureChecker, { /// Completes remaining checks on all receipts up to /// (current time - `timestamp_buffer_ns`). Returns them in two lists diff --git a/tap_integration_tests/tests/indexer_mock.rs b/tap_integration_tests/tests/indexer_mock.rs index 7877ffba..16c35572 100644 --- a/tap_integration_tests/tests/indexer_mock.rs +++ b/tap_integration_tests/tests/indexer_mock.rs @@ -17,7 +17,7 @@ use jsonrpsee::{ use tap_aggregator::jsonrpsee_helpers; use tap_core::{ manager::{ - adapters::{EscrowHandler, RAVRead, RAVStore, ReceiptRead, ReceiptStore}, + adapters::{SignatureChecker, RAVRead, RAVStore, ReceiptRead, ReceiptStore}, Manager, }, rav::SignedRAV, @@ -83,7 +83,7 @@ where #[async_trait] impl RpcServer for RpcManager where - E: ReceiptStore + ReceiptRead + RAVStore + RAVRead + EscrowHandler + Send + Sync + 'static, + E: ReceiptStore + ReceiptRead + RAVStore + RAVRead + SignatureChecker + Send + Sync + 'static, { async fn request( &self, @@ -147,7 +147,7 @@ where + ReceiptRead + RAVStore + RAVRead - + EscrowHandler + + SignatureChecker + Clone + Send + Sync @@ -182,7 +182,7 @@ async fn request_rav( threshold: usize, ) -> Result<()> where - E: ReceiptRead + RAVRead + RAVStore + EscrowHandler, + E: ReceiptRead + RAVRead + RAVStore + SignatureChecker, { // Create the aggregate_receipts request params let rav_request = manager From a321487768622b497e40ed21b40a46d88acf18de Mon Sep 17 00:00:00 2001 From: Gustavo Inacio Date: Thu, 23 Jan 2025 15:11:05 +0100 Subject: [PATCH 3/3] style: cargo fmt Signed-off-by: Gustavo Inacio --- tap_core/src/manager/adapters/mod.rs | 4 ++-- tap_core/src/manager/tap_manager.rs | 4 +++- tap_core/src/rav/request.rs | 2 +- tap_integration_tests/tests/indexer_mock.rs | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tap_core/src/manager/adapters/mod.rs b/tap_core/src/manager/adapters/mod.rs index ca3395c5..867a39ae 100644 --- a/tap_core/src/manager/adapters/mod.rs +++ b/tap_core/src/manager/adapters/mod.rs @@ -8,10 +8,10 @@ //! allows for easy integration with various storage solutions and verification //! procedures, thereby making the library adaptable to a wide range of use cases. -mod signature; mod rav; mod receipt; +mod signature; -pub use signature::SignatureChecker; pub use rav::*; pub use receipt::*; +pub use signature::SignatureChecker; diff --git a/tap_core/src/manager/tap_manager.rs b/tap_core/src/manager/tap_manager.rs index 4ecd1279..6bd0123a 100644 --- a/tap_core/src/manager/tap_manager.rs +++ b/tap_core/src/manager/tap_manager.rs @@ -3,7 +3,9 @@ use alloy::dyn_abi::Eip712Domain; -use super::adapters::{SignatureChecker, RAVRead, RAVStore, ReceiptDelete, ReceiptRead, ReceiptStore}; +use super::adapters::{ + RAVRead, RAVStore, ReceiptDelete, ReceiptRead, ReceiptStore, SignatureChecker, +}; use crate::{ rav::{RAVRequest, ReceiptAggregateVoucher, SignedRAV}, receipt::{ diff --git a/tap_core/src/rav/request.rs b/tap_core/src/rav/request.rs index f58fa14e..553698b8 100644 --- a/tap_core/src/rav/request.rs +++ b/tap_core/src/rav/request.rs @@ -4,7 +4,7 @@ use crate::{ rav::{ReceiptAggregateVoucher, SignedRAV}, receipt::{ - state::{Failed, Checked}, + state::{Checked, Failed}, ReceiptWithState, }, Error, diff --git a/tap_integration_tests/tests/indexer_mock.rs b/tap_integration_tests/tests/indexer_mock.rs index 16c35572..bf39ba53 100644 --- a/tap_integration_tests/tests/indexer_mock.rs +++ b/tap_integration_tests/tests/indexer_mock.rs @@ -17,7 +17,7 @@ use jsonrpsee::{ use tap_aggregator::jsonrpsee_helpers; use tap_core::{ manager::{ - adapters::{SignatureChecker, RAVRead, RAVStore, ReceiptRead, ReceiptStore}, + adapters::{RAVRead, RAVStore, ReceiptRead, ReceiptStore, SignatureChecker}, Manager, }, rav::SignedRAV,