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 96c16b2
Show file tree
Hide file tree
Showing 5 changed files with 387 additions and 21 deletions.
113 changes: 96 additions & 17 deletions explorer-mapper/src/block.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
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::blocks::block_info;
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 @@ -30,21 +40,48 @@ pub fn fill_block(ctx: &mut ProcessingContext, block: &BCBlock, block_id: BlockI
prev2: prev_info.1.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(),
block_info: map_block_info(&block_info)?,
value_flow: map_value_flow(block)?,
account_blocks: "".to_string(),
shards_info: None,
additional_info: None,
};
}

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 +104,54 @@ 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()?;

let mut res = Vec::new();
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(&mut update, &block_id, &tx)?;
}
}

todo!()
}
6 changes: 4 additions & 2 deletions explorer-mapper/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
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
Expand Down
79 changes: 79 additions & 0 deletions explorer-mapper/src/message.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use anyhow::{Context, Result};
use everscale_types::cell::CellBuilder;
use everscale_types::models::{IntAddr, Message, MsgInfo};
use explorer_models::schema::sql_types::MessageType;
use explorer_models::{Hash, MessageInfo, ProcessingContext};

#[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 (src, dst, msg_ty) = 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 = MessageInfo::from(msg.header());

ctx.messages.push(Message {
message_hash,
src_workchain,
src_address,
dst_workchain,
dst_address,

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_address,
src_workchain,
src_address,
message_hash,
message_type,
transaction_time,
message_value: info.value,
bounced: info.bounced,
bounce: info.bounce,
});

Ok(())
}

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

0 comments on commit 96c16b2

Please sign in to comment.