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 Field::new("block_height", DataType::UInt64, false),
35 Field::new("id", DataType::Binary, false),
36 Field::new("input_asset_ids", DataType::Binary, true),
38 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 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 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 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 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
158pub 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}