This repository was archived by the owner on Aug 3, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 131
Expand file tree
/
Copy pathshasta.rs
More file actions
223 lines (214 loc) · 8.93 KB
/
Copy pathshasta.rs
File metadata and controls
223 lines (214 loc) · 8.93 KB
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
use alloy_rlp::Decodable;
use log::warn;
use reth_evm_ethereum::taiko::ANCHOR_V4_GAS_LIMIT;
use reth_primitives::revm_primitives::SpecId;
use reth_primitives::TransactionSigned;
use crate::consts::ForkCondition;
use crate::input::GuestBatchInput;
use crate::manifest::DerivationSourceManifest;
#[cfg(not(feature = "std"))]
use crate::no_std::*;
use crate::utils::blobs::{decode_blob_data, zlib_decompress_data};
use crate::utils::shasta_rules::*;
/// Builds a default block manifest for a derivation source when validation fails.
fn make_default_manifest(
guest_batch_input: &GuestBatchInput,
last_parent_block_timestamp: u64,
last_parent_block_gas_limit: u64,
last_anchor_block_number: u64,
) -> DerivationSourceManifest {
let taiko_guest_batch_input = &guest_batch_input.taiko;
let proposal_timestamp = taiko_guest_batch_input.batch_proposed.proposal_timestamp();
let shasta_fork_timestamp = match guest_batch_input
.taiko
.chain_spec
.hard_forks
.get(&SpecId::SHASTA)
{
Some(ForkCondition::Timestamp(timestamp)) => *timestamp,
_ => unreachable!("shasta fork should be a timestamp fork"),
};
let timestamp_max_offset =
timestamp_max_offset_for_chain(guest_batch_input.taiko.chain_spec.chain_id());
let timestamp = clamp_timestamp_lower_bound(
last_parent_block_timestamp,
proposal_timestamp,
shasta_fork_timestamp,
timestamp_max_offset,
);
let coinbase = taiko_guest_batch_input.batch_proposed.proposer();
let anchor_block_number = last_anchor_block_number;
let gas_limit = if guest_batch_input
.inputs
.first()
.unwrap()
.parent_header
.number
== 0
{
last_parent_block_gas_limit
} else {
last_parent_block_gas_limit - ANCHOR_V4_GAS_LIMIT
};
let transactions = Vec::new();
DerivationSourceManifest::default_block_manifest(
timestamp,
coinbase,
anchor_block_number,
gas_limit,
transactions,
)
}
/// concat blob & decode a whole txlist, then
/// each block will get a portion of the txlist by its tx_nums
pub fn generate_transactions_for_shasta_blocks(
guest_batch_input: &GuestBatchInput,
) -> Vec<(Vec<TransactionSigned>, bool)> {
let taiko_guest_batch_input = &guest_batch_input.taiko;
let batch_proposal = &taiko_guest_batch_input.batch_proposed;
let data_sources = &taiko_guest_batch_input.data_sources;
let mut tx_list_bufs = Vec::new();
let last_anchor_block_number = guest_batch_input
.taiko
.prover_data
.last_anchor_block_number
.unwrap();
let last_parent_block_header = &guest_batch_input.inputs[0].parent_header;
let mut last_parent_block_timestamp = last_parent_block_header.timestamp;
let mut last_parent_block_gas_limit = last_parent_block_header.gas_limit;
for (idx, data_source) in data_sources.iter().enumerate() {
let use_blob = batch_proposal.blob_used();
let compressed_tx_list_buf = if use_blob {
let blob_data_bufs = data_source.tx_data_from_blob.clone();
let decoded_blob_data_concat = blob_data_bufs
.iter()
.map(|blob_data_buf| decode_blob_data(blob_data_buf))
.collect::<Vec<Vec<u8>>>()
.concat();
let sliced = batch_proposal
.blob_tx_slice_param_for_source(idx, &decoded_blob_data_concat)
.and_then(|(blob_offset, blob_size)| {
tracing::info!("blob_offset: {blob_offset}, blob_size: {blob_size}");
decoded_blob_data_concat
.get(blob_offset..blob_offset + blob_size)
.map(|s| s.to_vec())
})
.unwrap_or_default();
sliced
} else {
unreachable!("shasta does not use calldata");
};
// - Decode manifest from blob data
// - Extract transactions from manifest blocks
// - Distribute transactions to blocks
if idx == data_sources.len() - 1 {
assert!(
!data_source.is_forced_inclusion,
"last source should be normal source"
);
let protocol_manifest_bytes =
zlib_decompress_data(&compressed_tx_list_buf).unwrap_or_default();
let protocol_manifest =
match DerivationSourceManifest::decode(&mut protocol_manifest_bytes.as_ref()) {
Ok(manifest)
if validate_normal_proposal_manifest(
guest_batch_input,
&manifest,
last_anchor_block_number,
) =>
{
manifest
}
_ => {
let manifest = make_default_manifest(
guest_batch_input,
last_parent_block_timestamp,
last_parent_block_gas_limit,
last_anchor_block_number,
);
warn!(
"shasta block manifest is invalid, use default manifest: {:?}",
&manifest
);
manifest
}
};
// parent is pacaya means this is the first shasta block
let use_init_base_fee = guest_batch_input.inputs[0].parent_header.number == 0;
let min_base_fee =
min_base_fee_for_shasta_chain(guest_batch_input.taiko.chain_spec.chain_id());
if !validate_shasta_block_base_fee(
&guest_batch_input.inputs,
use_init_base_fee,
guest_batch_input.taiko.l2_grandparent_header.as_ref(),
min_base_fee,
) {
warn!("shasta block base fee is invalid, need double check");
panic!("shasta block base fee is invalid");
}
protocol_manifest
.blocks
.iter()
.enumerate()
.for_each(|(offset, block_manifest)| {
assert!(
validate_input_block_param(
block_manifest,
&guest_batch_input.inputs[idx + offset].block
),
"input block manifest is invalid"
);
tx_list_bufs.push((block_manifest.transactions.clone(), false))
});
} else {
assert!(
data_source.is_forced_inclusion,
"begin sources are force inclusion source"
);
let force_inc_source_bytes =
zlib_decompress_data(&compressed_tx_list_buf).unwrap_or_default();
let force_inc_source =
match DerivationSourceManifest::decode(&mut force_inc_source_bytes.as_ref()) {
Ok(manifest) if validate_force_inc_proposal_manifest(&manifest) => {
// overwrite force inc manifest
let mut force_inc_manifest = make_default_manifest(
guest_batch_input,
last_parent_block_timestamp,
last_parent_block_gas_limit,
last_anchor_block_number,
);
force_inc_manifest.blocks[0].transactions =
manifest.blocks[0].transactions.clone();
force_inc_manifest
}
_ => {
let manifest = make_default_manifest(
guest_batch_input,
last_parent_block_timestamp,
last_parent_block_gas_limit,
last_anchor_block_number,
);
warn!(
"force inclusion block manifest is invalid, use default manifest: {:?}",
&manifest
);
manifest
}
};
// force inc has only 1 block
let force_inc_block_manifest = &force_inc_source.blocks[0];
// update last parent block timestamp for next iteration
last_parent_block_timestamp = force_inc_block_manifest.timestamp;
last_parent_block_gas_limit = force_inc_block_manifest.gas_limit;
assert!(
validate_input_block_param(
force_inc_block_manifest,
&guest_batch_input.inputs[idx].block
),
"force inclusion source is invalid"
);
tx_list_bufs.push((force_inc_block_manifest.transactions.clone(), true));
}
}
tx_list_bufs
}