-
Notifications
You must be signed in to change notification settings - Fork 431
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
V3 agents rebase #2746
V3 agents rebase #2746
Changes from all commits
d7dc8af
c58d664
3151149
80ab924
4555704
423ad5f
b3a1f45
9dc552e
6b3a3bb
240d6ee
0bdb5e6
9fd8f8d
bcf40b6
f8008cb
4e16acc
2e5f00c
6f5e404
852b29b
f7911c1
e90d85e
2813272
233d93c
85f60b6
67adfd2
15d7a50
2719423
92ce7f1
dfd41ef
77060cc
8804d95
191da20
2ce86fa
05cd4e2
19faea7
a078621
5455b14
23567f8
f516184
10d647f
df6ee62
040bdbf
108cfd2
0736222
10c4fbc
a1d753f
535b637
72e65b4
bb2ad2c
33417b4
2c16b37
291eb93
0ba2b9c
2907581
1a1eb88
4e0c472
d4c587a
9f999a3
58e289f
a76a4c8
6f639e7
7bfe7cd
044b523
9f88da0
9448b66
863ecfd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,3 +28,4 @@ yarn-error.log | |
**/*.ignore | ||
.vscode | ||
|
||
tsconfig.editor.json | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
use std::fmt::Display; | ||
|
||
use eyre::Result; | ||
use eyre::{Context, Result}; | ||
use tracing::{debug, error, instrument}; | ||
|
||
use hyperlane_base::db::{DbError, HyperlaneRocksDB}; | ||
|
@@ -50,12 +50,6 @@ pub enum MerkleTreeBuilderError { | |
/// Root of the incremental merkle tree | ||
incremental_root: H256, | ||
}, | ||
/// Nonce was not found in DB, despite batch providing messages after | ||
#[error("Nonce was not found {nonce:?}")] | ||
UnavailableNonce { | ||
/// Root of prover's local merkle tree | ||
nonce: u32, | ||
}, | ||
Comment on lines
-53
to
-58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we dont need this anymore? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. didn't find any uses of it |
||
/// MerkleTreeBuilder attempts Prover operation and receives ProverError | ||
#[error(transparent)] | ||
ProverError(#[from] ProverError), | ||
|
@@ -65,6 +59,9 @@ pub enum MerkleTreeBuilderError { | |
/// DB Error | ||
#[error("{0}")] | ||
DbError(#[from] DbError), | ||
/// Some other error occured. | ||
#[error("Failed to build the merkle tree: {0}")] | ||
Other(String), | ||
} | ||
|
||
impl MerkleTreeBuilder { | ||
|
@@ -81,54 +78,38 @@ impl MerkleTreeBuilder { | |
#[instrument(err, skip(self), level="debug", fields(prover_latest_index=self.count()-1))] | ||
pub fn get_proof( | ||
&self, | ||
leaf_index: u32, | ||
message_nonce: u32, | ||
root_index: u32, | ||
) -> Result<Proof, MerkleTreeBuilderError> { | ||
) -> Result<Option<Proof>, MerkleTreeBuilderError> { | ||
let Some(leaf_index) = self | ||
.db | ||
.retrieve_message_id_by_nonce(&message_nonce)? | ||
.and_then(|message_id| self.db.retrieve_merkle_leaf_index_by_message_id(&message_id).ok().flatten()) | ||
else { | ||
return Ok(None); | ||
}; | ||
self.prover | ||
.prove_against_previous(leaf_index as usize, root_index as usize) | ||
.map(Option::from) | ||
.map_err(Into::into) | ||
} | ||
|
||
fn ingest_nonce(&mut self, nonce: u32) -> Result<(), MerkleTreeBuilderError> { | ||
match self.db.retrieve_message_id_by_nonce(&nonce) { | ||
Ok(Some(leaf)) => { | ||
debug!(nonce, "Ingesting leaf"); | ||
self.prover.ingest(leaf).expect("!tree full"); | ||
self.incremental.ingest(leaf); | ||
assert_eq!(self.prover.root(), self.incremental.root()); | ||
Ok(()) | ||
} | ||
Ok(None) => { | ||
error!("We should not arrive here"); | ||
Err(MerkleTreeBuilderError::UnavailableNonce { nonce }) | ||
} | ||
Err(e) => Err(e.into()), | ||
} | ||
} | ||
|
||
pub fn count(&self) -> u32 { | ||
self.prover.count() as u32 | ||
} | ||
|
||
#[instrument(err, skip(self), level = "debug")] | ||
pub async fn update_to_index(&mut self, index: u32) -> Result<(), MerkleTreeBuilderError> { | ||
if index >= self.count() { | ||
let starting_index = self.prover.count() as u32; | ||
for i in starting_index..=index { | ||
self.db.wait_for_message_nonce(i).await?; | ||
self.ingest_nonce(i)?; | ||
} | ||
|
||
let prover_root = self.prover.root(); | ||
let incremental_root = self.incremental.root(); | ||
if prover_root != incremental_root { | ||
return Err(MerkleTreeBuilderError::MismatchedRoots { | ||
prover_root, | ||
incremental_root, | ||
}); | ||
} | ||
pub async fn ingest_message_id(&mut self, message_id: H256) -> Result<()> { | ||
const CTX: &str = "When ingesting message id"; | ||
debug!(?message_id, "Ingesting leaf"); | ||
self.prover.ingest(message_id).expect("tree full"); | ||
self.incremental.ingest(message_id); | ||
match self.prover.root().eq(&self.incremental.root()) { | ||
true => Ok(()), | ||
false => Err(MerkleTreeBuilderError::MismatchedRoots { | ||
prover_root: self.prover.root(), | ||
incremental_root: self.incremental.root(), | ||
}), | ||
} | ||
|
||
Ok(()) | ||
.context(CTX) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub(crate) mod builder; | ||
pub(crate) mod processor; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
use std::{ | ||
fmt::{Debug, Formatter}, | ||
sync::Arc, | ||
time::Duration, | ||
}; | ||
|
||
use async_trait::async_trait; | ||
use derive_new::new; | ||
use eyre::Result; | ||
use hyperlane_base::db::HyperlaneRocksDB; | ||
use hyperlane_core::{HyperlaneDomain, MerkleTreeInsertion}; | ||
use prometheus::IntGauge; | ||
use tokio::sync::RwLock; | ||
use tracing::debug; | ||
|
||
use crate::processor::ProcessorExt; | ||
|
||
use super::builder::MerkleTreeBuilder; | ||
|
||
/// Finds unprocessed merkle tree insertions and adds them to the prover sync | ||
#[derive(new)] | ||
pub struct MerkleTreeProcessor { | ||
db: HyperlaneRocksDB, | ||
metrics: MerkleTreeProcessorMetrics, | ||
prover_sync: Arc<RwLock<MerkleTreeBuilder>>, | ||
#[new(default)] | ||
daniel-savu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
leaf_index: u32, | ||
} | ||
|
||
impl Debug for MerkleTreeProcessor { | ||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||
write!( | ||
f, | ||
"MerkleTreeProcessor {{ leaf_index: {:?} }}", | ||
self.leaf_index | ||
) | ||
} | ||
} | ||
|
||
#[async_trait] | ||
impl ProcessorExt for MerkleTreeProcessor { | ||
/// The domain this processor is getting merkle tree hook insertions from. | ||
fn domain(&self) -> &HyperlaneDomain { | ||
self.db.domain() | ||
} | ||
|
||
/// One round of processing, extracted from infinite work loop for | ||
/// testing purposes. | ||
async fn tick(&mut self) -> Result<()> { | ||
if let Some(insertion) = self.next_unprocessed_leaf()? { | ||
// Feed the message to the prover sync | ||
self.prover_sync | ||
.write() | ||
.await | ||
.ingest_message_id(insertion.message_id()) | ||
.await?; | ||
|
||
// Increase the leaf index to move on to the next leaf | ||
self.leaf_index += 1; | ||
} else { | ||
tokio::time::sleep(Duration::from_secs(1)).await; | ||
} | ||
Ok(()) | ||
} | ||
} | ||
|
||
impl MerkleTreeProcessor { | ||
fn next_unprocessed_leaf(&mut self) -> Result<Option<MerkleTreeInsertion>> { | ||
let leaf = if let Some(insertion) = self | ||
.db | ||
.retrieve_merkle_tree_insertion_by_leaf_index(&self.leaf_index)? | ||
{ | ||
// Update the metrics | ||
self.metrics | ||
.max_leaf_index_gauge | ||
.set(insertion.index() as i64); | ||
Some(insertion) | ||
} else { | ||
debug!(leaf_index=?self.leaf_index, "No message found in DB for leaf index"); | ||
None | ||
}; | ||
Ok(leaf) | ||
} | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct MerkleTreeProcessorMetrics { | ||
max_leaf_index_gauge: IntGauge, | ||
} | ||
|
||
impl MerkleTreeProcessorMetrics { | ||
pub fn new() -> Self { | ||
Self { | ||
max_leaf_index_gauge: IntGauge::new( | ||
"max_leaf_index_gauge", | ||
"The max merkle tree leaf index", | ||
) | ||
.unwrap(), | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,20 +2,20 @@ use std::fmt::Debug; | |
|
||
use async_trait::async_trait; | ||
use eyre::Result; | ||
use tracing::{debug, error, trace}; | ||
|
||
use hyperlane_base::db::HyperlaneRocksDB; | ||
use hyperlane_core::{ | ||
GasPaymentKey, HyperlaneMessage, InterchainGasExpenditure, InterchainGasPayment, | ||
TxCostEstimate, TxOutcome, U256, | ||
}; | ||
|
||
use crate::msg::gas_payment::policies::GasPaymentPolicyOnChainFeeQuoting; | ||
use crate::settings::{ | ||
matching_list::MatchingList, GasPaymentEnforcementConf, GasPaymentEnforcementPolicy, | ||
}; | ||
use tracing::{debug, error, trace}; | ||
|
||
use self::policies::{GasPaymentPolicyMinimum, GasPaymentPolicyNone}; | ||
use crate::{ | ||
msg::gas_payment::policies::GasPaymentPolicyOnChainFeeQuoting, | ||
settings::{ | ||
matching_list::MatchingList, GasPaymentEnforcementConf, GasPaymentEnforcementPolicy, | ||
}, | ||
}; | ||
|
||
mod policies; | ||
|
||
|
@@ -148,12 +148,11 @@ mod test { | |
H256, U256, | ||
}; | ||
|
||
use super::GasPaymentEnforcer; | ||
use crate::settings::{ | ||
matching_list::MatchingList, GasPaymentEnforcementConf, GasPaymentEnforcementPolicy, | ||
}; | ||
|
||
use super::GasPaymentEnforcer; | ||
|
||
#[tokio::test] | ||
async fn test_empty_whitelist() { | ||
test_utils::run_test_db(|db| async move { | ||
|
@@ -195,7 +194,7 @@ mod test { | |
test_utils::run_test_db(|db| async move { | ||
let hyperlane_db = | ||
HyperlaneRocksDB::new(&HyperlaneDomain::new_test_domain("test_no_match"), db); | ||
let matching_list = serde_json::from_str(r#"[{"originDomain": 234}]"#).unwrap(); | ||
let matching_list = serde_json::from_str(r#"[{"origindomain": 234}]"#).unwrap(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this necessary? assuming this is from Mattie's config change but curious if this implies that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think what this tests is whether the config is robust against casing inconsistencies and that |
||
let enforcer = GasPaymentEnforcer::new( | ||
// Require a payment | ||
vec![GasPaymentEnforcementConf { | ||
|
@@ -339,7 +338,7 @@ mod test { | |
let recipient_address = "0xbb000000000000000000000000000000000000bb"; | ||
|
||
let matching_list = serde_json::from_str( | ||
&format!(r#"[{{"senderAddress": "{sender_address}", "recipientAddress": "{recipient_address}"}}]"#) | ||
&format!(r#"[{{"senderaddress": "{sender_address}", "recipientaddress": "{recipient_address}"}}]"#) | ||
).unwrap(); | ||
|
||
let enforcer = GasPaymentEnforcer::new( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whats this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added by @mattiecnvr afaik