loom_types_entities/
latest_block.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use alloy_consensus::BlockHeader;
use alloy_primitives::map::B256HashMap;
use alloy_primitives::{Address, BlockHash, BlockNumber, B256};
use alloy_rpc_types::state::{AccountOverride, StateOverride};
use alloy_rpc_types::{Block, BlockTransactions, Header, Log, Transaction};

use loom_types_blockchain::GethStateUpdateVec;

pub struct LatestBlock {
    pub block_number: BlockNumber,
    pub block_hash: BlockHash,
    pub block_header: Option<Header>,
    pub block_with_txs: Option<Block>,
    pub logs: Option<Vec<Log>>,
    pub diff: Option<GethStateUpdateVec>,
}

impl LatestBlock {
    pub fn hash(&self) -> BlockHash {
        self.block_hash
    }

    pub fn parent_hash(&self) -> Option<BlockHash> {
        self.block_header.as_ref().map(|x| x.parent_hash)
    }
    pub fn number(&self) -> BlockNumber {
        self.block_number
    }

    pub fn number_and_hash(&self) -> (BlockNumber, BlockHash) {
        (self.block_number, self.block_hash)
    }

    pub fn new(block_number: BlockNumber, block_hash: BlockHash) -> Self {
        Self { block_number, block_hash, block_header: None, block_with_txs: None, logs: None, diff: None }
    }

    pub fn node_state_override(&self) -> StateOverride {
        let mut cur_state_override = StateOverride::default();

        if let Some(cur_diff) = self.diff.as_ref() {
            for diff_entry in cur_diff {
                for (addr, state) in diff_entry {
                    let account = cur_state_override.entry(*addr).or_insert(AccountOverride::default());
                    account.balance = state.balance;
                    account.nonce = state.nonce;

                    let diff: B256HashMap<B256> = state.storage.iter().map(|(k, v)| (*k, *v)).collect();
                    account.state_diff = Some(diff);
                }
            }
        }
        cur_state_override
    }

    pub fn txs(&self) -> Option<&Vec<Transaction>> {
        if let Some(block) = &self.block_with_txs {
            if let BlockTransactions::Full(txs) = &block.transactions {
                return Some(txs);
            }
        }
        None
    }

    pub fn coinbase(&self) -> Option<Address> {
        if let Some(block) = &self.block_with_txs {
            return Some(block.header.beneficiary());
        }
        None
    }

    pub fn update(
        &mut self,
        block_number: BlockNumber,
        block_hash: BlockHash,
        block_header: Option<Header>,
        block_with_txes: Option<Block>,
        logs: Option<Vec<Log>>,
        diff: Option<GethStateUpdateVec>,
    ) -> bool {
        if block_number >= self.block_number {
            let is_new = block_number > self.block_number;

            if block_number > self.block_number || block_hash != self.block_hash {
                *self = Self::new(block_number, block_hash);
            }

            if let Some(x) = block_header {
                self.block_header = Some(x);
            }
            if let Some(x) = block_with_txes {
                self.block_with_txs = Some(x);
            }
            if let Some(x) = logs {
                self.logs = Some(x);
            }
            if let Some(x) = diff {
                self.diff = Some(x)
            }

            is_new
        } else {
            false
        }
    }
}