Skip to content

Commit

Permalink
make changes to old indexer
Browse files Browse the repository at this point in the history
  • Loading branch information
bowenyang007 committed Jul 18, 2023
1 parent 00f081a commit fa96bee
Show file tree
Hide file tree
Showing 9 changed files with 390 additions and 82 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-- This file should undo anything in `up.sql`
DROP INDEX IF EXISTS at_version_index;
DROP INDEX IF EXISTS at_insat_index;
DROP TABLE IF EXISTS account_transactions;
ALTER TABLE objects
ALTER COLUMN owner_address DROP NOT NULL;
ALTER TABLE objects
ALTER COLUMN guid_creation_num DROP NOT NULL;
ALTER TABLE objects
ALTER COLUMN allow_ungated_transfer DROP NOT NULL;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-- Your SQL goes here
-- Records transactions - account pairs. Account here can represent
-- user account, resource account, or object account.
CREATE TABLE IF NOT EXISTS account_transactions (
transaction_version BIGINT NOT NULL,
account_address VARCHAR(66) NOT NULL,
inserted_at TIMESTAMP NOT NULL DEFAULT NOW(),
PRIMARY KEY (account_address, transaction_version)
);
CREATE INDEX IF NOT EXISTS at_version_index ON account_transactions (transaction_version DESC);
CREATE INDEX IF NOT EXISTS at_insat_index ON account_transactions (inserted_at);
ALTER TABLE objects
ALTER COLUMN owner_address
SET NOT NULL;
ALTER TABLE objects
ALTER COLUMN guid_creation_num
SET NOT NULL;
ALTER TABLE objects
ALTER COLUMN allow_ungated_transfer
SET NOT NULL;
136 changes: 136 additions & 0 deletions crates/indexer/src/models/coin_models/account_transactions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0

// This is required because a diesel macro makes clippy sad
#![allow(clippy::extra_unused_lifetimes)]
#![allow(clippy::unused_unit)]

use crate::{
models::{
token_models::v2_token_utils::ObjectWithMetadata, user_transactions::UserTransaction,
},
schema::account_transactions,
util::standardize_address,
};
use aptos_api_types::{DeleteResource, Event, Transaction, WriteResource, WriteSetChange};
use field_count::FieldCount;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

pub type AccountTransactionPK = (String, i64);

#[derive(Debug, Deserialize, FieldCount, Identifiable, Insertable, Serialize)]
#[diesel(primary_key(account_address, transaction_version))]
#[diesel(table_name = account_transactions)]
pub struct AccountTransaction {
pub transaction_version: i64,
pub account_address: String,
}

impl AccountTransaction {
/// This table will record every transaction that touch an account which could be
/// a user account, an object, or a resource account.
/// We will consider all transactions that modify a resource or event associated with a particular account.
/// We will do 1 level of redirection for now (e.g. if it's an object, we will record the owner as account address).
/// We will also consider transactions that the account signed or is part of a multi sig / multi agent.
/// TODO: recursively find the parent account of an object
/// TODO: include table items in the detection path
pub fn from_transaction(
transaction: &Transaction,
) -> anyhow::Result<HashMap<AccountTransactionPK, Self>> {
let (events, wscs, signatures, txn_version) = match transaction {
Transaction::UserTransaction(inner) => (
&inner.events,
&inner.info.changes,
UserTransaction::get_signatures(inner, inner.info.version.0 as i64, 0),
inner.info.version.0 as i64,
),
Transaction::GenesisTransaction(inner) => (
&inner.events,
&inner.info.changes,
vec![],
inner.info.version.0 as i64,
),
Transaction::BlockMetadataTransaction(inner) => (
&inner.events,
&inner.info.changes,
vec![],
inner.info.version.0 as i64,
),
_ => {
return Ok(HashMap::new());
},
};
let mut account_transactions = HashMap::new();
for sig in &signatures {
account_transactions.insert((sig.signer.clone(), txn_version), Self {
transaction_version: txn_version,
account_address: sig.signer.clone(),
});
}
for event in events {
account_transactions.extend(Self::from_event(event, txn_version));
}
for wsc in wscs {
match wsc {
WriteSetChange::DeleteResource(res) => {
account_transactions.extend(Self::from_delete_resource(res, txn_version)?);
},
WriteSetChange::WriteResource(res) => {
account_transactions.extend(Self::from_write_resource(res, txn_version)?);
},
_ => {},
}
}
Ok(account_transactions)
}

/// Base case, record event account address. We don't really have to worry about
/// objects here because it'll be taken care of in the resource section
fn from_event(event: &Event, txn_version: i64) -> HashMap<AccountTransactionPK, Self> {
let account_address = standardize_address(&event.guid.account_address.to_string());
HashMap::from([((account_address.clone(), txn_version), Self {
transaction_version: txn_version,
account_address,
})])
}

/// Base case, record resource account. If the resource is an object, then we record the owner as well
/// This handles partial deletes as well
fn from_write_resource(
write_resource: &WriteResource,
txn_version: i64,
) -> anyhow::Result<HashMap<AccountTransactionPK, Self>> {
let mut result = HashMap::new();
let account_address = standardize_address(&write_resource.address.to_string());
result.insert((account_address.clone(), txn_version), Self {
transaction_version: txn_version,
account_address,
});
if let Some(inner) = &ObjectWithMetadata::from_write_resource(write_resource, txn_version)?
{
result.insert((inner.object_core.get_owner_address(), txn_version), Self {
transaction_version: txn_version,
account_address: inner.object_core.get_owner_address(),
});
}
Ok(result)
}

/// Base case, record resource account.
/// TODO: If the resource is an object, then we need to look for the latest owner. This isn't really possible
/// right now given we have parallel threads so it'll be very difficult to ensure that we have the correct
/// latest owner
fn from_delete_resource(
delete_resource: &DeleteResource,
txn_version: i64,
) -> anyhow::Result<HashMap<AccountTransactionPK, Self>> {
let mut result = HashMap::new();
let account_address = standardize_address(&delete_resource.address.to_string());
result.insert((account_address.clone(), txn_version), Self {
transaction_version: txn_version,
account_address,
});
Ok(result)
}
}
1 change: 1 addition & 0 deletions crates/indexer/src/models/coin_models/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0

pub mod account_transactions;
pub mod coin_activities;
pub mod coin_balances;
pub mod coin_infos;
Expand Down
35 changes: 22 additions & 13 deletions crates/indexer/src/models/user_transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,21 +92,30 @@ impl UserTransaction {
},
epoch,
},
txn.request
.signature
.as_ref()
.map(|s| {
Signature::from_user_transaction(
s,
&txn.request.sender.to_string(),
version,
block_height,
)
.unwrap()
})
.unwrap_or_default(), // empty vec if signature is None
Self::get_signatures(txn, version, block_height),
)
}

/// Empty vec if signature is None
pub fn get_signatures(
txn: &APIUserTransaction,
version: i64,
block_height: i64,
) -> Vec<Signature> {
txn.request
.signature
.as_ref()
.map(|s| {
Signature::from_user_transaction(
s,
&txn.request.sender.to_string(),
version,
block_height,
)
.unwrap()
})
.unwrap_or_default() // empty vec if signature is None
}
}

// Prevent conflicts with other things named `Transaction`
Expand Down
Loading

0 comments on commit fa96bee

Please sign in to comment.