skar_schema_fuel/
lib.rs

1use std::sync::Arc;
2
3use anyhow::{anyhow, Context, Result};
4use arrow2::array::{new_empty_array, Array};
5use arrow2::chunk::Chunk;
6use arrow2::compute;
7use arrow2::datatypes::{DataType, Field, Schema, SchemaRef};
8
9mod util;
10
11pub use util::project_schema;
12
13pub type ArrowChunk = Chunk<Box<dyn Array>>;
14
15pub fn block_header() -> SchemaRef {
16    Schema::from(vec![
17        Field::new("id", DataType::Binary, false),
18        Field::new("da_height", DataType::UInt64, false),
19        Field::new("transactions_count", DataType::UInt64, false),
20        Field::new("message_receipt_count", DataType::UInt64, false),
21        Field::new("transactions_root", DataType::Binary, false),
22        Field::new("message_receipt_root", DataType::Binary, false),
23        Field::new("height", DataType::UInt64, false),
24        Field::new("prev_root", DataType::Binary, false),
25        Field::new("time", DataType::Int64, false),
26        Field::new("application_hash", DataType::Binary, false),
27    ])
28    .into()
29}
30
31pub fn transaction() -> SchemaRef {
32    Schema::from(vec![
33        // block number
34        Field::new("block_height", DataType::UInt64, false),
35        Field::new("id", DataType::Binary, false),
36        // vec
37        Field::new("input_asset_ids", DataType::Binary, true),
38        // vec
39        Field::new("input_contracts", DataType::Binary, true),
40        Field::new("input_contract_utxo_id", DataType::Binary, true),
41        Field::new("input_contract_balance_root", DataType::Binary, true),
42        Field::new("input_contract_state_root", DataType::Binary, true),
43        Field::new(
44            "input_contract_tx_pointer_block_height",
45            DataType::UInt64,
46            true,
47        ),
48        Field::new("input_contract_tx_pointer_tx_index", DataType::UInt64, true),
49        Field::new("input_contract", DataType::Binary, true),
50        Field::new("gas_price", DataType::UInt64, true),
51        Field::new("gas_limit", DataType::UInt64, true),
52        Field::new("maturity", DataType::UInt64, true),
53        Field::new("mint_amount", DataType::UInt64, true),
54        Field::new("mint_asset_id", DataType::Binary, true),
55        Field::new("tx_pointer_block_height", DataType::UInt64, true),
56        Field::new("tx_pointer_tx_index", DataType::UInt64, true),
57        Field::new("tx_type", DataType::UInt8, false),
58        Field::new("output_contract_input_index", DataType::UInt64, true),
59        Field::new("output_contract_balance_root", DataType::Binary, true),
60        Field::new("output_contract_state_root", DataType::Binary, true),
61        // vec
62        Field::new("witnesses", DataType::Binary, true),
63        Field::new("receipts_root", DataType::Binary, true),
64        Field::new("status", DataType::UInt8, true),
65        Field::new("time", DataType::Int64, false),
66        Field::new("reason", DataType::Utf8, true),
67        Field::new("script", DataType::Binary, true),
68        Field::new("script_data", DataType::Binary, true),
69        Field::new("bytecode_witness_index", DataType::UInt64, true),
70        Field::new("bytecode_length", DataType::UInt64, true),
71        Field::new("salt", DataType::Binary, true),
72    ])
73    .into()
74}
75
76pub fn receipt() -> SchemaRef {
77    Schema::from(vec![
78        // receipt index is unique per block
79        Field::new("receipt_index", DataType::UInt64, false),
80        Field::new("root_contract_id", DataType::Binary, true),
81        Field::new("tx_id", DataType::Binary, false),
82        Field::new("block_height", DataType::UInt64, false),
83        Field::new("pc", DataType::UInt64, true),
84        Field::new("is", DataType::UInt64, true),
85        Field::new("to", DataType::Binary, true),
86        Field::new("to_address", DataType::Binary, true),
87        Field::new("amount", DataType::UInt64, true),
88        Field::new("asset_id", DataType::Binary, true),
89        Field::new("gas", DataType::UInt64, true),
90        Field::new("param1", DataType::UInt64, true),
91        Field::new("param2", DataType::UInt64, true),
92        Field::new("val", DataType::UInt64, true),
93        Field::new("ptr", DataType::UInt64, true),
94        Field::new("digest", DataType::Binary, true),
95        Field::new("reason", DataType::UInt64, true),
96        Field::new("ra", DataType::UInt64, true),
97        Field::new("rb", DataType::UInt64, true),
98        Field::new("rc", DataType::UInt64, true),
99        Field::new("rd", DataType::UInt64, true),
100        Field::new("len", DataType::UInt64, true),
101        Field::new("receipt_type", DataType::UInt8, false),
102        Field::new("result", DataType::UInt64, true),
103        Field::new("gas_used", DataType::UInt64, true),
104        Field::new("data", DataType::Binary, true),
105        Field::new("sender", DataType::Binary, true),
106        Field::new("recipient", DataType::Binary, true),
107        Field::new("nonce", DataType::Binary, true),
108        Field::new("contract_id", DataType::Binary, true),
109        Field::new("sub_id", DataType::Binary, true),
110    ])
111    .into()
112}
113
114pub fn input() -> SchemaRef {
115    Schema::from(vec![
116        // for mapping
117        Field::new("tx_id", DataType::Binary, false),
118        Field::new("block_height", DataType::UInt64, false),
119        Field::new("input_type", DataType::UInt8, false),
120        Field::new("utxo_id", DataType::Binary, true),
121        Field::new("owner", DataType::Binary, true),
122        Field::new("amount", DataType::UInt64, true),
123        Field::new("asset_id", DataType::Binary, true),
124        Field::new("tx_pointer_block_height", DataType::UInt64, true),
125        Field::new("tx_pointer_tx_index", DataType::UInt64, true),
126        Field::new("witness_index", DataType::UInt64, true),
127        Field::new("predicate_gas_used", DataType::UInt64, true),
128        Field::new("predicate", DataType::Binary, true),
129        Field::new("predicate_data", DataType::Binary, true),
130        Field::new("balance_root", DataType::Binary, true),
131        Field::new("state_root", DataType::Binary, true),
132        Field::new("contract", DataType::Binary, true),
133        Field::new("sender", DataType::Binary, true),
134        Field::new("recipient", DataType::Binary, true),
135        Field::new("nonce", DataType::Binary, true),
136        Field::new("data", DataType::Binary, true),
137    ])
138    .into()
139}
140
141pub fn output() -> SchemaRef {
142    Schema::from(vec![
143        // for mapping
144        Field::new("tx_id", DataType::Binary, false),
145        Field::new("block_height", DataType::UInt64, false),
146        Field::new("output_type", DataType::UInt8, false),
147        Field::new("to", DataType::Binary, true),
148        Field::new("amount", DataType::UInt64, true),
149        Field::new("asset_id", DataType::Binary, true),
150        Field::new("input_index", DataType::UInt64, true),
151        Field::new("balance_root", DataType::Binary, true),
152        Field::new("state_root", DataType::Binary, true),
153        Field::new("contract", DataType::Binary, true),
154    ])
155    .into()
156}
157
158/*
159pub fn block_header() -> SchemaRef {
160    Schema::from(vec![
161        Field::new("number", DataType::UInt64, false),
162        Field::new("hash", hash_dt(), false),
163        Field::new("parent_hash", hash_dt(), false),
164        Field::new("nonce", DataType::Binary, true),
165        Field::new("sha3_uncles", hash_dt(), false),
166        Field::new("logs_bloom", DataType::Binary, false),
167        Field::new("transactions_root", hash_dt(), false),
168        Field::new("state_root", hash_dt(), false),
169        Field::new("receipts_root", hash_dt(), false),
170        Field::new("miner", addr_dt(), false),
171        Field::new("difficulty", quantity_dt(), true),
172        Field::new("total_difficulty", quantity_dt(), true),
173        Field::new("extra_data", DataType::Binary, false),
174        Field::new("size", quantity_dt(), false),
175        Field::new("gas_limit", quantity_dt(), false),
176        Field::new("gas_used", quantity_dt(), false),
177        Field::new("timestamp", quantity_dt(), false),
178        Field::new("uncles", DataType::Binary, true),
179        Field::new("base_fee_per_gas", quantity_dt(), true),
180    ])
181    .into()
182}
183
184pub fn transaction() -> SchemaRef {
185    Schema::from(vec![
186        Field::new("block_hash", hash_dt(), false),
187        Field::new("block_number", DataType::UInt64, false),
188        Field::new("from", addr_dt(), true),
189        Field::new("gas", quantity_dt(), false),
190        Field::new("gas_price", quantity_dt(), true),
191        Field::new("hash", hash_dt(), false),
192        Field::new("input", DataType::Binary, false),
193        Field::new("nonce", quantity_dt(), false),
194        Field::new("to", addr_dt(), true),
195        Field::new("transaction_index", DataType::UInt64, false),
196        Field::new("value", quantity_dt(), false),
197        Field::new("v", quantity_dt(), true),
198        Field::new("r", quantity_dt(), true),
199        Field::new("s", quantity_dt(), true),
200        Field::new("max_priority_fee_per_gas", quantity_dt(), true),
201        Field::new("max_fee_per_gas", quantity_dt(), true),
202        Field::new("chain_id", quantity_dt(), true),
203        Field::new("cumulative_gas_used", quantity_dt(), false),
204        Field::new("effective_gas_price", quantity_dt(), false),
205        Field::new("gas_used", quantity_dt(), false),
206        Field::new("contract_address", addr_dt(), true),
207        Field::new("logs_bloom", DataType::Binary, false),
208        Field::new("type", DataType::UInt8, true),
209        Field::new("root", hash_dt(), true),
210        Field::new("status", DataType::UInt8, true),
211        Field::new("sighash", DataType::Binary, true),
212    ])
213    .into()
214}
215
216pub fn log() -> SchemaRef {
217    Schema::from(vec![
218        Field::new("removed", DataType::Boolean, true),
219        Field::new("log_index", DataType::UInt64, false),
220        Field::new("transaction_index", DataType::UInt64, false),
221        Field::new("transaction_hash", hash_dt(), false),
222        Field::new("block_hash", hash_dt(), false),
223        Field::new("block_number", DataType::UInt64, false),
224        Field::new("address", addr_dt(), false),
225        Field::new("data", DataType::Binary, false),
226        Field::new("topic0", DataType::Binary, true),
227        Field::new("topic1", DataType::Binary, true),
228        Field::new("topic2", DataType::Binary, true),
229        Field::new("topic3", DataType::Binary, true),
230    ])
231    .into()
232}
233*/
234
235pub fn concat_chunks(chunks: &[Arc<ArrowChunk>]) -> Result<ArrowChunk> {
236    if chunks.is_empty() {
237        return Err(anyhow!("can't concat 0 chunks"));
238    }
239
240    let num_cols = chunks[0].columns().len();
241
242    let cols = (0..num_cols)
243        .map(|col| {
244            let arrs = chunks
245                .iter()
246                .map(|chunk| {
247                    chunk
248                        .columns()
249                        .get(col)
250                        .map(|col| col.as_ref())
251                        .context("get column")
252                })
253                .collect::<Result<Vec<_>>>()?;
254            compute::concatenate::concatenate(&arrs).context("concat arrays")
255        })
256        .collect::<Result<Vec<_>>>()?;
257
258    Ok(ArrowChunk::new(cols))
259}
260
261pub fn empty_chunk(schema: &Schema) -> ArrowChunk {
262    let mut cols = Vec::new();
263    for field in schema.fields.iter() {
264        cols.push(new_empty_array(field.data_type().clone()));
265    }
266    ArrowChunk::new(cols)
267}
268
269#[cfg(test)]
270mod tests {
271    use super::*;
272
273    #[test]
274    fn smoke_test_schema_constructors() {
275        block_header();
276        transaction();
277        receipt();
278        input();
279        output();
280    }
281}