Skip to content

Commit

Permalink
wip: transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
0xdeafbeef committed Jul 2, 2024
1 parent 9a20f29 commit 47f4f02
Show file tree
Hide file tree
Showing 5 changed files with 413 additions and 24 deletions.
117 changes: 98 additions & 19 deletions explorer-mapper/src/block.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
use anyhow::Result;
use everscale_types::models::{Block as BCBlock, BlockId, BlockInfo as BCBlockInfo, PrevBlockRef};
use explorer_models::{Block, BlockInfo, ExtBlkRef, GlobalVersion, HashInsert, ProcessingContext};
use everscale_types::models::{
Block as BCBlock, BlockExtra, BlockId, BlockInfo as BCBlockInfo, PrevBlockRef,
};
use explorer_models::schema::sql_types::State;
use explorer_models::{
to_json_value, AccountUpdate, BlkPrevInfo, Block, BlockInfo, ExtBlkRef, GlobalVersion,
HashInsert, JsonValue, ProcessingContext, ValueFlow,
};

use crate::transaction::process_transaction;

pub fn fill_block(ctx: &mut ProcessingContext, block: &BCBlock, block_id: BlockId) -> Result<()> {
let block_info = block.load_info()?;
let extra = block.load_extra()?;
let prev_info = match block_info.load_prev_ref()? {
PrevBlockRef::Single(rf) => (rf, None),
PrevBlockRef::AfterMerge { left, right } => (left, Some(right)),
Expand All @@ -27,24 +36,53 @@ pub fn fill_block(ctx: &mut ProcessingContext, block: &BCBlock, block_id: BlockI
hash: prev_info.0.root_hash.0,
},
prev1_seqno: prev_info.0.seqno,
prev2: prev_info.1.map(|rf| HashInsert {
prev2: prev_info.1.as_ref().map(|rf| HashInsert {
hash: rf.root_hash.0,
}),
prev2_seqno: prev_info.1.map(|rf| rf.seqno),
prev2_seqno: prev_info.1.as_ref().map(|rf| rf.seqno),
prev_key_block: block_info.prev_key_block_seqno,
block_info: "".to_string(),
value_flow: "".to_string(),
account_blocks: "".to_string(),
block_info: map_block_info(&block_info)?,
value_flow: map_value_flow(block)?,
account_blocks: map_account_blocks(&extra, block_id)?,
shards_info: None,
additional_info: None,
};

Ok(())
}

fn fill_block_info(
ctx: &mut ProcessingContext,
block: &BCBlock,
block_info: &BCBlockInfo,
) -> Result<()> {
fn map_block_info(block_info: &BCBlockInfo) -> Result<JsonValue> {
let master_ref = match block_info.load_master_ref()? {
Some(rf) => Some(ExtBlkRef {
end_lt: rf.end_lt,
seq_no: rf.seqno,
root_hash: rf.root_hash.0.into(),
}),
None => None,
};
let prev_ref = block_info.load_prev_ref()?;
let prev_ref = match prev_ref {
PrevBlockRef::Single(s) => BlkPrevInfo::Block {
prev: ExtBlkRef {
end_lt: s.end_lt,
seq_no: s.seqno,
root_hash: s.root_hash.0.into(),
},
},
PrevBlockRef::AfterMerge { left, right } => BlkPrevInfo::Blocks {
prev1: ExtBlkRef {
end_lt: left.end_lt,
seq_no: left.seqno,
root_hash: left.root_hash.0.into(),
},
prev2: ExtBlkRef {
end_lt: right.end_lt,
seq_no: right.seqno,
root_hash: right.root_hash.0.into(),
},
},
};

let block_info = BlockInfo {
version: block_info.version,
after_merge: block_info.after_merge,
Expand All @@ -67,12 +105,53 @@ fn fill_block_info(
capabilities: block_info.gen_software.capabilities.into_inner(),
}),

master_ref: Some(ExtBlkRef {
end_lt: block_info.master_ref,
seq_no: 0,
root_hash: HashInsert {},
}),
prev_ref: (),
prev_vert_ref: None,
master_ref,
prev_ref,
prev_vert_ref: None, // doesn't exist in real world
};

Ok(to_json_value(&block_info))
}

fn map_value_flow(block: &BCBlock) -> Result<JsonValue> {
let value_flow = block.load_value_flow()?;
let value_flow = ValueFlow {
from_prev_blk: value_flow.from_prev_block.tokens.into_inner() as u64,
to_next_blk: value_flow.to_next_block.tokens.into_inner() as u64,
imported: value_flow.imported.tokens.into_inner() as u64,
exported: value_flow.exported.tokens.into_inner() as u64,
fees_collected: value_flow.fees_collected.tokens.into_inner() as u64,
fees_imported: value_flow.fees_imported.tokens.into_inner() as u64,
recovered: value_flow.recovered.tokens.into_inner() as u64,
created: value_flow.created.tokens.into_inner() as u64,
minted: value_flow.minted.tokens.into_inner() as u64,
};

Ok(to_json_value(&value_flow))
}

fn map_account_blocks(block: &BlockExtra, block_id: BlockId) -> Result<JsonValue> {
let account_blocks = block.account_blocks.load()?;

for account in account_blocks.values() {
let (cc, block) = account?;
let transactions = block.transactions;

let mut update = AccountUpdate {
address: block.account.0.into(),
wc: block_id.shard.workchain() as i8,
last_transaction_time: 0,
last_transaction_lt: 0,
creator: None,
state: State::NonExist,
deleted: false,
};
for tx in transactions.values() {
let tx = tx?;
let tx = tx.1.load()?;
process_transaction(todo!(), &mut update, &block_id, &tx)?;
}
}

todo!()
}
8 changes: 5 additions & 3 deletions explorer-mapper/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use everscale_types::models::Block;
use everscale_types::models::{Block, BlockId};
use explorer_models::ProcessingContext;

mod block;
mod message;
mod transaction;

pub fn fill_processing_context(block: Block) -> ProcessingContext {
pub fn fill_processing_context(block: Block, block_id: BlockId) -> ProcessingContext {
let mut context = ProcessingContext::default();
context.blocks.push(block);

context
}
102 changes: 102 additions & 0 deletions explorer-mapper/src/message.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use anyhow::Result;
use everscale_types::cell::CellBuilder;
use everscale_types::models::{IntAddr, Message, MsgInfo};
use explorer_models::schema::sql_types::MessageType;
use explorer_models::{
Hash, Message as MessageDb, MessageInfo, ProcessingContext, TransactionMessage,
};

#[allow(clippy::too_many_arguments)]
pub fn process_message(
ctx: &mut ProcessingContext,
block_hash: Hash,
transaction_hash: Hash,
is_out: bool,
index_in_transaction: u16,
message: &Message<'_>,
account: Hash,
lt: u64,
wc: i8,
transaction_time: u32,
) -> Result<()> {
let msg_cell = CellBuilder::build_from(message)?;
let msg_hash = msg_cell.repr_hash().0.into();

let (src, dst, message_type) = match &message.info {
MsgInfo::Int(i) => (map_addr(&i.src)?, map_addr(&i.dst)?, MessageType::Internal),
MsgInfo::ExtIn(m) => ((None, 0), map_addr(&m.dst)?, MessageType::ExternalIn),
MsgInfo::ExtOut(m) => (map_addr(&m.src)?, (None, 0), MessageType::ExternalOut),
};

let info = message_info(message);

ctx.messages.push(MessageDb {
message_hash: msg_hash,
src_workchain: src.1,
src_address: src.0,
dst_workchain: dst.1,
dst_address: dst.0,
message_type,
message_value: info.value,
ihr_fee: info.ihr_fee,
fwd_fee: info.fwd_fee,
import_fee: info.import_fee,
created_lt: info.created_lt,
created_at: info.created_at,
bounced: info.bounced,
bounce: info.bounce,
});

ctx.transaction_messages.push(TransactionMessage {
transaction_hash,
index_in_transaction,
is_out,
transaction_lt: lt,
transaction_account_workchain: wc,
transaction_account_address: account,
block_hash,
dst_workchain: dst.1,
dst_address: dst.0,
src_workchain: src.1,
src_address: src.0,
message_hash: msg_hash,
message_type,
transaction_time,
message_value: info.value,
bounced: info.bounced,
bounce: info.bounce,
});

Ok(())
}

fn message_info(message: &Message<'_>) -> MessageInfo {
match &message.info {
MsgInfo::Int(m) => MessageInfo {
value: m.value.tokens.into_inner() as u64,
ihr_fee: m.ihr_fee.into_inner() as u64,
fwd_fee: m.fwd_fee.into_inner() as u64,
bounce: m.bounce,
bounced: m.bounced,
created_lt: m.created_lt,
created_at: m.created_at,
..Default::default()
},
MsgInfo::ExtIn(m) => MessageInfo {
import_fee: m.import_fee.into_inner() as u64,
..Default::default()
},
MsgInfo::ExtOut(m) => MessageInfo {
created_lt: m.created_lt,
created_at: m.created_at,
..Default::default()
},
}
}

pub fn map_addr(addr: &IntAddr) -> Result<(Option<Hash>, i8)> {
match addr {
IntAddr::Std(add) => Ok((Some(add.address.0.into()), add.workchain)),
IntAddr::Var(_) => anyhow::bail!("Unsupported address type"),
}
}
Loading

0 comments on commit 47f4f02

Please sign in to comment.