feat: Add entrypoint (#202)

* feat: add DCI message definitions


#time 4m

#time 0m

* feat: Add add_entrypoint to TransactionChangesBuilder

#time 15m


#time 0m

* fix: Make entrypoints into a HashSet instead of Vec

#time 0m

* fix: Rollback on message index change in ContractSlot

#time 5m

* fix: Ignore examples in docstrings when running cargo test

---------

Co-authored-by: Louise Poole <louise@datarevenue.com>
This commit is contained in:
dianacarvalho1
2025-05-13 12:31:36 +01:00
committed by GitHub
parent b13b2b3cc0
commit 2a77cf965c
5 changed files with 95 additions and 3 deletions

View File

@@ -149,6 +149,26 @@ message ContractChange {
repeated AccountBalanceChange token_balances = 6;
}
// DCI entities
// An entrypoint to be used for DCI analysis
message EntryPoint {
// The entrypoint id. Recommended to use 'target:signature'.
string id = 1;
// The target contract to analyse this entrypoint on.
bytes target = 2;
// The signature of the function to analyse.
bytes signature = 3;
}
// A contract and associated storage changes
message StorageChanges {
// The contract's address
bytes address = 1;
// The contract's storage changes
repeated ContractSlot slots = 2;
}
// Aggregate entities
// A set of changes aggregated by transaction.
@@ -165,6 +185,16 @@ message TransactionChanges {
repeated ProtocolComponent component_changes = 4;
// An array of balance changes to components.
repeated BalanceChange balance_changes = 5;
// An array of newly added entrypoints. Used for DCI enabled protocols.
repeated EntryPoint entrypoints = 6;
}
// A set of storage changes aggregated by transaction.
message TransactionStorageChanges {
// The transaction instance that results in the changes.
Transaction tx = 1;
// Contains the storage changes induced by the above transaction.
repeated StorageChanges storage_changes = 2;
}
// A set of transaction changes within a single block.
@@ -174,4 +204,7 @@ message BlockChanges {
Block block = 1;
// The set of transaction changes observed in the specified block.
repeated TransactionChanges changes = 2;
// The set of all storage changes from the specified block. Intended as input for the Dynamic Contract Indexer.
// Should be left empty for protocols that do not use the DCI.
repeated TransactionStorageChanges storage_changes = 3;
}

View File

@@ -5,6 +5,7 @@ plugins:
opt:
- file_descriptor_set=false
- type_attribute=.tycho.evm.v1.Transaction=#[derive(Eq\, Hash)]
- type_attribute=.tycho.evm.v1.EntryPoint=#[derive(Eq\, Hash)]
- remote: buf.build/community/neoeinstein-prost-crate:v0.3.1
out: src/pb
opt: no_features

View File

@@ -192,7 +192,7 @@ pub fn aggregate_balances_changes(
///
/// # Example
///
/// ```
/// ```ignore
/// let predicate = |log_address: &[u8], transfer_address: &[u8]| -> bool {
/// // Your predicate logic here, e.g., checking if the address matches a specific pattern.
/// true

View File

@@ -28,6 +28,7 @@ pub struct TransactionChangesBuilder {
entity_changes: HashMap<String, InterimEntityChanges>,
component_changes: HashMap<String, ProtocolComponent>,
balance_changes: HashMap<(Vec<u8>, Vec<u8>), BalanceChange>,
entrypoints: HashSet<EntryPoint>,
}
impl TransactionChangesBuilder {
@@ -151,6 +152,13 @@ impl TransactionChangesBuilder {
.insert((change.component_id.clone(), change.token.clone()), change.clone());
}
/// Adds a new entrypoint to the transaction. It adds to the set of already existing
/// entrypoints.
pub fn add_entrypoint(&mut self, entrypoint: &EntryPoint) {
self.entrypoints
.insert(entrypoint.clone());
}
pub fn build(self) -> Option<TransactionChanges> {
let tx_changes = TransactionChanges {
tx: self.tx,
@@ -172,6 +180,10 @@ impl TransactionChangesBuilder {
.balance_changes
.into_values()
.collect::<Vec<_>>(),
entrypoints: self
.entrypoints
.into_iter()
.collect::<Vec<_>>(),
};
if tx_changes.is_empty() {
None
@@ -325,7 +337,7 @@ impl ProtocolComponent {
///
/// # Example
///
/// ```
/// ```ignore
/// let attributes_to_check = vec![
/// ("attribute1".to_string(), vec![1, 2, 3]),
/// ("attribute2".to_string(), vec![4, 5, 6]),
@@ -367,7 +379,7 @@ impl ProtocolComponent {
///
/// # Example
///
/// ```
/// ```ignore
/// let attribute_name = "attribute1";
/// if let Some(value) = instance.get_attribute_value(attribute_name) {
/// // Use the attribute value

View File

@@ -173,6 +173,34 @@ pub struct ContractChange {
#[prost(message, repeated, tag="6")]
pub token_balances: ::prost::alloc::vec::Vec<AccountBalanceChange>,
}
// DCI entities
/// An entrypoint to be used for DCI analysis
#[derive(Eq, Hash)]
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct EntryPoint {
/// The entrypoint id. Recommended to use 'target:signature'.
#[prost(string, tag="1")]
pub id: ::prost::alloc::string::String,
/// The target contract to analyse this entrypoint on.
#[prost(bytes="vec", tag="2")]
pub target: ::prost::alloc::vec::Vec<u8>,
/// The signature of the function to analyse.
#[prost(bytes="vec", tag="3")]
pub signature: ::prost::alloc::vec::Vec<u8>,
}
/// A contract and associated storage changes
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StorageChanges {
/// The contract's address
#[prost(bytes="vec", tag="1")]
pub address: ::prost::alloc::vec::Vec<u8>,
/// The contract's storage changes
#[prost(message, repeated, tag="2")]
pub slots: ::prost::alloc::vec::Vec<ContractSlot>,
}
// Aggregate entities
/// A set of changes aggregated by transaction.
@@ -196,6 +224,20 @@ pub struct TransactionChanges {
/// An array of balance changes to components.
#[prost(message, repeated, tag="5")]
pub balance_changes: ::prost::alloc::vec::Vec<BalanceChange>,
/// An array of newly added entrypoints. Used for DCI enabled protocols.
#[prost(message, repeated, tag="6")]
pub entrypoints: ::prost::alloc::vec::Vec<EntryPoint>,
}
/// A set of storage changes aggregated by transaction.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct TransactionStorageChanges {
/// The transaction instance that results in the changes.
#[prost(message, optional, tag="1")]
pub tx: ::core::option::Option<Transaction>,
/// Contains the storage changes induced by the above transaction.
#[prost(message, repeated, tag="2")]
pub storage_changes: ::prost::alloc::vec::Vec<StorageChanges>,
}
/// A set of transaction changes within a single block.
/// This message must be the output of your substreams module.
@@ -208,6 +250,10 @@ pub struct BlockChanges {
/// The set of transaction changes observed in the specified block.
#[prost(message, repeated, tag="2")]
pub changes: ::prost::alloc::vec::Vec<TransactionChanges>,
/// The set of all storage changes from the specified block. Intended as input for the Dynamic Contract Indexer.
/// Should be left empty for protocols that do not use the DCI.
#[prost(message, repeated, tag="3")]
pub storage_changes: ::prost::alloc::vec::Vec<TransactionStorageChanges>,
}
/// Enum to specify the type of a change.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]