Skip to content

Commit

Permalink
feat: store substate_id in events (#986)
Browse files Browse the repository at this point in the history
Description
---
* Updated the `events` database table for the new field
* Updated database API and managers to use substate ids instead of
component addresses
* Builtin vault events (e.g. `std.vault.deposit`) now emit two events:
one has the vault as `substate_id` and the other has the resource. This
is done to allow queries by both criteria

Motivation and Context
---
Up until now events stored the component address related to it. This is
not general enough now because we want also to emit events that can be
related to other type of substates (e.g. resources or vaults). This PR
changes the `component_address` field for `substate_id` for events in
the whole project (from database to APIs)

How Has This Been Tested?
---
* Existing unit and integration tests pass.
* Manually inspected the content of the new `substate_id` field in
different types of events

What process can a PR reviewer use to test or verify this change?
---
Emit any type of event and check the new `substate_id` field value

Breaking Changes
---

- [ ] None
- [ ] Requires data directory to be deleted
- [x] Event fields change (`substate_id` instead of `component_address`)
so it requires network reset

---------

Co-authored-by: Stan Bondi <sdbondi@users.noreply.github.com>
  • Loading branch information
mrnaveira and sdbondi authored Mar 25, 2024
1 parent 4924728 commit 86dd4f9
Show file tree
Hide file tree
Showing 25 changed files with 394 additions and 383 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import CodeBlockExpand from "../../Components/CodeBlock";
import { useTheme } from "@mui/material/styles";
import type { Event } from "@tariproject/typescript-bindings";

function RowData({ component_address, template_address, topic, tx_hash, payload }: Event, index: number) {
function RowData({ substate_id, template_address, topic, tx_hash, payload }: Event, index: number) {
const [open, setOpen] = useState(false);
const theme = useTheme();
return (
Expand All @@ -51,8 +51,8 @@ function RowData({ component_address, template_address, topic, tx_hash, payload
</DataTableCell>
<DataTableCell>{topic}</DataTableCell>
<DataTableCell>
{shortenString(component_address)}
{component_address && <CopyToClipboard copy={component_address} />}
{shortenString(substate_id)}
{substate_id && <CopyToClipboard copy={substate_id} />}
</DataTableCell>
<DataTableCell>
{shortenString(template_address)}
Expand Down Expand Up @@ -89,16 +89,16 @@ export default function Events({ data }: { data: Event[] }) {
<TableRow>
<TableCell width={90}>Payload</TableCell>
<TableCell>Topic</TableCell>
<TableCell>Component Address</TableCell>
<TableCell>Substate Id</TableCell>
<TableCell>Template Address</TableCell>
<TableCell>Transaction Hash</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map(({ component_address, template_address, topic, tx_hash, payload }: Event, index: number) => {
{data.map(({ substate_id, template_address, topic, tx_hash, payload }: Event, index: number) => {
return (
<RowData
component_address={component_address}
substate_id={substate_id}
template_address={template_address}
topic={topic}
tx_hash={tx_hash}
Expand Down
27 changes: 13 additions & 14 deletions applications/tari_indexer/src/graphql/model/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ use std::{collections::BTreeMap, str::FromStr, sync::Arc};
use async_graphql::{Context, EmptyMutation, EmptySubscription, Object, Schema, SimpleObject};
use log::*;
use serde::{Deserialize, Serialize};
use tari_template_lib::{models::ObjectKey, prelude::ComponentAddress, Hash};
use tari_engine_types::substate::SubstateId;
use tari_template_lib::Hash;
use tari_transaction::TransactionId;

use crate::substate_manager::SubstateManager;
Expand All @@ -35,7 +36,7 @@ const LOG_TARGET: &str = "tari::indexer::graphql::events";
#[derive(SimpleObject, Clone, Debug, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Event {
pub component_address: Option<[u8; ObjectKey::LENGTH]>,
pub substate_id: Option<String>,
pub template_address: [u8; 32],
pub tx_hash: [u8; 32],
pub topic: String,
Expand All @@ -45,9 +46,7 @@ pub struct Event {
impl Event {
fn from_engine_event(event: tari_engine_types::events::Event) -> Result<Self, anyhow::Error> {
Ok(Self {
component_address: event
.component_address()
.map(|comp_addr| comp_addr.as_object_key().into_array()),
substate_id: event.substate_id().map(|sub_id| sub_id.to_string()),
template_address: event.template_address().into_array(),
tx_hash: event.tx_hash().into_array(),
topic: event.topic(),
Expand Down Expand Up @@ -89,20 +88,20 @@ impl EventQuery {
Ok(events)
}

pub async fn get_events_for_component(
pub async fn get_events_for_substate(
&self,
ctx: &Context<'_>,
component_address: String,
substate_id: String,
version: Option<u32>,
) -> Result<Vec<Event>, anyhow::Error> {
let version = version.unwrap_or_default();
info!(
target: LOG_TARGET,
"Querying events for component_address = {}, starting from version = {}", component_address, version
"Querying events for substate_id = {}, starting from version = {}", substate_id, version
);
let substate_manager = ctx.data_unchecked::<Arc<SubstateManager>>();
let events = substate_manager
.scan_events_for_substate_from_network(ComponentAddress::from_str(&component_address)?, Some(version))
.scan_events_for_substate_from_network(SubstateId::from_str(&substate_id)?, Some(version))
.await?
.iter()
.map(|e| Event::from_engine_event(e.clone()))
Expand Down Expand Up @@ -137,7 +136,7 @@ impl EventQuery {
pub async fn save_event(
&self,
ctx: &Context<'_>,
component_address: String,
substate_id: String,
template_address: String,
tx_hash: String,
topic: String,
Expand All @@ -146,17 +145,17 @@ impl EventQuery {
) -> Result<Event, anyhow::Error> {
info!(
target: LOG_TARGET,
"Saving event for component_address = {}, tx_hash = {} and topic = {}", component_address, tx_hash, topic
"Saving event for substate_id = {}, tx_hash = {} and topic = {}", substate_id, tx_hash, topic
);

let component_address = ComponentAddress::from_hex(&component_address)?;
let substate_id = SubstateId::from_str(&substate_id)?;
let template_address = Hash::from_str(&template_address)?;
let tx_hash = TransactionId::from_hex(&tx_hash)?;

let payload = serde_json::from_str(&payload)?;
let substate_manager = ctx.data_unchecked::<Arc<SubstateManager>>();
substate_manager.save_event_to_db(
component_address,
&substate_id,
template_address,
tx_hash,
topic.clone(),
Expand All @@ -165,7 +164,7 @@ impl EventQuery {
)?;

Ok(Event {
component_address: Some(component_address.as_object_key().into_array()),
substate_id: Some(substate_id.to_string()),
template_address: template_address.into_array(),
tx_hash: tx_hash.into_array(),
topic,
Expand Down
27 changes: 12 additions & 15 deletions applications/tari_indexer/src/substate_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@ use tari_indexer_lib::{
substate_scanner::SubstateScanner,
NonFungibleSubstate,
};
use tari_template_lib::{
models::TemplateAddress,
prelude::{ComponentAddress, Metadata},
};
use tari_template_lib::{models::TemplateAddress, prelude::Metadata};
use tari_transaction::TransactionId;
use tari_validator_node_rpc::client::{SubstateResult, TariValidatorNodeRpcClientFactory};

Expand Down Expand Up @@ -305,7 +302,7 @@ impl SubstateManager {

pub fn save_event_to_db(
&self,
component_address: ComponentAddress,
substate_id: &SubstateId,
template_address: TemplateAddress,
tx_hash: TransactionId,
topic: String,
Expand All @@ -314,7 +311,7 @@ impl SubstateManager {
) -> Result<(), anyhow::Error> {
let mut tx = self.substate_store.create_write_tx()?;
let new_event = NewEvent {
component_address: Some(component_address.to_string()),
substate_id: Some(substate_id.to_string()),
template_address: template_address.to_string(),
tx_hash: tx_hash.to_string(),
topic,
Expand Down Expand Up @@ -348,7 +345,7 @@ impl SubstateManager {

pub async fn scan_events_for_substate_from_network(
&self,
component_address: ComponentAddress,
substate_id: SubstateId,
version: Option<u32>,
) -> Result<Vec<Event>, anyhow::Error> {
let mut events = vec![];
Expand All @@ -359,15 +356,15 @@ impl SubstateManager {
let stored_versions_in_db;
{
let mut tx = self.substate_store.create_read_tx()?;
stored_versions_in_db = tx.get_stored_versions_of_events(&component_address, version)?;
stored_versions_in_db = tx.get_stored_versions_of_events(&substate_id, version)?;

let stored_events = match tx.get_all_events(&component_address) {
let stored_events = match tx.get_all_events(&substate_id) {
Ok(events) => events,
Err(e) => {
info!(
target: LOG_TARGET,
"Failed to get all events for component_address = {}, version = {} with error = {}",
component_address,
"Failed to get all events for substate_id = {}, version = {} with error = {}",
substate_id,
version,
e
);
Expand All @@ -388,7 +385,7 @@ impl SubstateManager {
}
let network_version_events = self
.substate_scanner
.get_events_for_component_and_version(component_address, v)
.get_events_for_substate_and_version(&substate_id, v)
.await?;
events.extend(network_version_events);
}
Expand All @@ -399,11 +396,11 @@ impl SubstateManager {
// check if there are newest events for this component address in the network
let network_events = self
.substate_scanner
.get_events_for_component(component_address, Some(version))
.get_events_for_substate(&substate_id, Some(version))
.await?;

// stores the newest network events to the db
// because the same component address with different version
// because the same substate_id with different version
// can be processed in the same transaction, we need to avoid
// duplicates
for (version, event) in network_events {
Expand All @@ -412,7 +409,7 @@ impl SubstateManager {
let topic = event.topic();
let payload = event.payload();
self.save_event_to_db(
component_address,
&substate_id,
template_address,
tx_hash,
topic,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-- This file should undo anything in `up.sql`
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alter table events
rename column component_address to substate_id;
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ use std::{convert::TryFrom, str::FromStr};

use diesel::sql_types::{Integer, Nullable, Text};
use serde::{Deserialize, Serialize};
use tari_template_lib::{prelude::ComponentAddress, Hash};
use tari_engine_types::substate::SubstateId;
use tari_template_lib::Hash;

use crate::substate_storage_sqlite::schema::*;

Expand All @@ -38,7 +39,7 @@ pub struct Event {
pub topic: String,
pub payload: String,
pub version: i32,
pub component_address: Option<String>,
pub substate_id: Option<String>,
}

#[derive(Debug, Clone, Insertable, AsChangeset)]
Expand All @@ -50,7 +51,7 @@ pub struct NewEvent {
pub topic: String,
pub payload: String,
pub version: i32,
pub component_address: Option<String>,
pub substate_id: Option<String>,
}

#[derive(Debug, Clone, Insertable, AsChangeset)]
Expand All @@ -75,18 +76,14 @@ pub struct EventData {
#[diesel(sql_type = Integer)]
pub version: i32,
#[diesel(sql_type = Nullable<Text>)]
pub component_address: Option<String>,
pub substate_id: Option<String>,
}

impl TryFrom<EventData> for crate::graphql::model::events::Event {
type Error = anyhow::Error;

fn try_from(event_data: EventData) -> Result<Self, Self::Error> {
let component_address = event_data
.component_address
.map(|comp_addr| ComponentAddress::from_str(comp_addr.as_str()))
.transpose()?
.map(|comp_addr| comp_addr.as_object_key().into_array());
let substate_id = event_data.substate_id;

let template_address = Hash::from_hex(&event_data.template_address)?.into_array();

Expand All @@ -95,7 +92,7 @@ impl TryFrom<EventData> for crate::graphql::model::events::Event {
let payload = serde_json::from_str(event_data.payload.as_str())?;

Ok(Self {
component_address,
substate_id,
template_address,
tx_hash,
payload,
Expand All @@ -108,17 +105,17 @@ impl TryFrom<EventData> for tari_engine_types::events::Event {
type Error = anyhow::Error;

fn try_from(event_data: EventData) -> Result<Self, Self::Error> {
let component_address = event_data
.component_address
let substate_id = event_data
.substate_id
.clone()
.map(|comp_addr| ComponentAddress::from_str(comp_addr.as_str()))
.map(|sub_id| SubstateId::from_str(&sub_id))
.transpose()?;
let template_address = Hash::from_hex(&event_data.template_address)?;
let tx_hash = Hash::from_hex(&event_data.tx_hash)?;
let payload = serde_json::from_str(event_data.payload.as_str())?;

Ok(Self::new(
component_address,
substate_id,
template_address,
tx_hash,
event_data.topic,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ diesel::table! {
topic -> Text,
payload -> Text,
version -> Integer,
component_address -> Nullable<Text>,
substate_id -> Nullable<Text>,
}
}

Expand Down
Loading

0 comments on commit 86dd4f9

Please sign in to comment.