essential_node_db/query_range/
finalized.rs

1//! Finalized queries query for the most recent version of a key less than or equal to a
2//! given block number or solution set index for blocks that have been finalized.
3
4use crate::{blob_from_words, words_from_blob, QueryError};
5use essential_node_db_sql as sql;
6use essential_types::{ContentAddress, Key, Value, Word};
7use rusqlite::{named_params, Connection, OptionalExtension};
8
9/// Query the most recent value for a key in a contract's state
10/// that was set at or before the given block number.
11///
12/// This is inclusive of the block's state (..=block_number).
13pub fn query_state_inclusive_block(
14    conn: &Connection,
15    contract_ca: &ContentAddress,
16    key: &Key,
17    block_number: Word,
18) -> Result<Option<Value>, QueryError> {
19    let mut stmt = conn.prepare(sql::query::QUERY_STATE_AT_BLOCK_FINALIZED)?;
20    let value_blob: Option<Vec<u8>> = stmt
21        .query_row(
22            named_params! {
23                ":contract_ca": contract_ca.0,
24                ":key": blob_from_words(key),
25                ":block_number": block_number,
26            },
27            |row| row.get("value"),
28        )
29        .optional()?;
30    Ok(value_blob.as_deref().map(words_from_blob))
31}
32
33/// Query for the most recent version value of a key in a contracts state
34/// that was set before the given block number.
35///
36/// This is exclusive of the block's state (..block_number).
37pub fn query_state_exclusive_block(
38    conn: &Connection,
39    contract_ca: &ContentAddress,
40    key: &Key,
41    block_number: Word,
42) -> Result<Option<Value>, QueryError> {
43    match block_number.checked_sub(1) {
44        Some(block_number) => query_state_inclusive_block(conn, contract_ca, key, block_number),
45        None => Ok(None),
46    }
47}
48
49/// Query for the most recent version value of a key in a contracts state
50/// that was set at or before the given block number and
51/// solution set index (within that block).
52///
53/// This is inclusive of the solution set's state mutations
54/// `..=block_number[..=solution_set_index]`
55pub fn query_state_inclusive_solution_set(
56    conn: &Connection,
57    contract_ca: &ContentAddress,
58    key: &Key,
59    block_number: Word,
60    solution_set_index: u64,
61) -> Result<Option<Value>, QueryError> {
62    let mut stmt = conn.prepare(sql::query::QUERY_STATE_AT_SOLUTION_SET_FINALIZED)?;
63    let value_blob: Option<Vec<u8>> = stmt
64        .query_row(
65            named_params! {
66                ":contract_ca": contract_ca.0,
67                ":key": blob_from_words(key),
68                ":block_number": block_number,
69                ":solution_set_index": solution_set_index,
70            },
71            |row| row.get("value"),
72        )
73        .optional()?;
74    Ok(value_blob.as_deref().map(words_from_blob))
75}
76
77/// Query for the most recent version value of a key in a contracts state
78/// that was set at or before the given block number and before the
79/// solution set index (within that block).
80///
81/// This is exclusive of the solution set's state `..=block_number[..solution_set_index]`.
82pub fn query_state_exclusive_solution_set(
83    conn: &Connection,
84    contract_ca: &ContentAddress,
85    key: &Key,
86    block_number: Word,
87    solution_set_index: u64,
88) -> Result<Option<Value>, QueryError> {
89    match solution_set_index.checked_sub(1) {
90        Some(solution_set_index) => query_state_inclusive_solution_set(
91            conn,
92            contract_ca,
93            key,
94            block_number,
95            solution_set_index,
96        ),
97        None => query_state_exclusive_block(conn, contract_ca, key, block_number),
98    }
99}