Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix db sanity check #4820

Merged
merged 4 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions massa-db-exports/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,6 @@ pub const KEY_LEN_SER_ERROR: &str = "critical: key length serialization failed";
// deferred calls
pub const DEFERRED_CALL_DESER_ERROR: &str = "critical: message deserialization failed";
pub const DEFERRED_CALL_SER_ERROR: &str = "critical: message serialization failed";
pub const DEFERRED_CALL_TOTAL_GAS: &str = "deferred_call_total_gas";

pub const DEFERRED_CALL_TOTAL_REGISTERED: &str = "deferred_call_total_registered";
8 changes: 4 additions & 4 deletions massa-deferred-calls/src/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,12 @@ impl Serializer<DeferredCall> for DeferredCallSerializer {
#[derive(Clone)]
pub struct DeferredCallDeserializer {
slot_deserializer: SlotDeserializer,
address_deserializer: AddressDeserializer,
string_deserializer: StringDeserializer<U16VarIntDeserializer, u16>,
vec_u8_deserializer: VecU8Deserializer,
pub(crate) address_deserializer: AddressDeserializer,
pub(crate) string_deserializer: StringDeserializer<U16VarIntDeserializer, u16>,
pub(crate) vec_u8_deserializer: VecU8Deserializer,
pub(crate) amount_deserializer: AmountDeserializer,
pub(crate) u64_var_int_deserializer: U64VarIntDeserializer,
bool_deserializer: BoolDeserializer,
pub(crate) bool_deserializer: BoolDeserializer,
}

impl DeferredCallDeserializer {
Expand Down
133 changes: 131 additions & 2 deletions massa-deferred-calls/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
use call::{DeferredCallDeserializer, DeferredCallSerializer};
use config::DeferredCallsConfig;
use macros::{DEFERRED_CALL_TOTAL_GAS, DEFERRED_CALL_TOTAL_REGISTERED};
use macros::{
CALL_FIELD_CANCELED, CALL_FIELD_COINS, CALL_FIELD_FEE, CALL_FIELD_MAX_GAS,
CALL_FIELD_PARAMETERS, CALL_FIELD_SENDER_ADDRESS, CALL_FIELD_TARGET_ADDRESS,
CALL_FIELD_TARGET_FUNCTION, CALL_FIELD_TARGET_SLOT,
};
use massa_db_exports::{
DBBatch, ShareableMassaDBController, CRUD_ERROR, DEFERRED_CALLS_PREFIX,
DEFERRED_CALL_DESER_ERROR, DEFERRED_CALL_SER_ERROR, KEY_DESER_ERROR, STATE_CF,
DEFERRED_CALL_DESER_ERROR, DEFERRED_CALL_SER_ERROR, DEFERRED_CALL_TOTAL_GAS,
DEFERRED_CALL_TOTAL_REGISTERED, KEY_DESER_ERROR, STATE_CF,
};
use massa_models::address::Address;
use massa_serialization::{DeserializeError, Deserializer, Serializer};
use registry_changes::{
DeferredCallRegistryChanges, DeferredRegistryChangesDeserializer,
Expand Down Expand Up @@ -434,6 +440,129 @@ impl DeferredCallRegistry {
DeferredRegistryGasChange::Keep => {}
}
}

pub fn is_key_value_valid(&self, serialized_key: &[u8], serialized_value: &[u8]) -> bool {
if serialized_key.starts_with(DEFERRED_CALLS_PREFIX.as_bytes()) {
// check for [DEFERRED_CALLS_PREFIX][slot]
if let Ok((_rest, slot)) =
self.registry_changes_deserializer
.slot_deserializer
.deserialize::<DeserializeError>(&serialized_key[DEFERRED_CALLS_PREFIX.len()..])
{
// check for [DEFERRED_CALLS_PREFIX][slot][SLOT_TOTAL_GAS]
if serialized_key
.starts_with(&deferred_call_slot_total_gas_key!(&slot.to_bytes_key()))
{
return self
.call_deserializer
.u64_var_int_deserializer
.deserialize::<DeserializeError>(serialized_value)
.is_ok();
} else if serialized_key
.starts_with(&deferred_call_slot_base_fee_key!(&slot.to_bytes_key()))
{
// check for [DEFERRED_CALLS_PREFIX][slot][SLOT_BASE_FEE]
return self
.call_deserializer
.amount_deserializer
.deserialize::<DeserializeError>(serialized_value)
.is_ok();
} else {
// check for [DEFERRED_CALLS_PREFIX][slot][CALLS_TAG][id][CALL_FIELD_X_TAG]

// [DEFERRED_CALLS_PREFIX][slot][CALLS_TAG]
let k = deferred_slot_call_prefix_key!(&slot.to_bytes_key());
let rest_key = &serialized_key[k.len()..];

if let Ok((rest, _id)) = self
.call_id_deserializer
.deserialize::<DeserializeError>(rest_key)
{
match rest[0] {
CALL_FIELD_SENDER_ADDRESS => {
let res: Result<(&[u8], Address), nom::Err<DeserializeError<'_>>> =
self.call_deserializer
.address_deserializer
.deserialize::<DeserializeError>(serialized_value);

return res.is_ok();
}
CALL_FIELD_TARGET_SLOT => {
return self
.registry_changes_deserializer
.slot_deserializer
.deserialize::<DeserializeError>(serialized_value)
.is_ok()
}
CALL_FIELD_TARGET_ADDRESS => {
let res: Result<(&[u8], Address), nom::Err<DeserializeError<'_>>> =
self.call_deserializer
.address_deserializer
.deserialize::<DeserializeError>(serialized_value);
return res.is_ok();
}
CALL_FIELD_TARGET_FUNCTION => {
return self
.call_deserializer
.string_deserializer
.deserialize::<DeserializeError>(serialized_value)
.is_ok()
}
CALL_FIELD_PARAMETERS => {
return self
.call_deserializer
.vec_u8_deserializer
.deserialize::<DeserializeError>(serialized_value)
.is_ok()
}
CALL_FIELD_MAX_GAS => {
return self
.call_deserializer
.u64_var_int_deserializer
.deserialize::<DeserializeError>(serialized_value)
.is_ok()
}
CALL_FIELD_FEE => {
return self
.call_deserializer
.amount_deserializer
.deserialize::<DeserializeError>(serialized_value)
.is_ok()
}
CALL_FIELD_CANCELED => {
return self
.call_deserializer
.bool_deserializer
.deserialize::<DeserializeError>(serialized_value)
.is_ok();
}
CALL_FIELD_COINS => {
return self
.call_deserializer
.amount_deserializer
.deserialize::<DeserializeError>(serialized_value)
.is_ok();
}
_ => {}
}
}
}
}
} else if serialized_key.eq(DEFERRED_CALL_TOTAL_GAS.as_bytes()) {
return self
.registry_changes_deserializer
.effective_total_gas_deserializer
.deserialize::<DeserializeError>(serialized_value)
.is_ok();
} else if serialized_key.eq(DEFERRED_CALL_TOTAL_REGISTERED.as_bytes()) {
return self
.registry_changes_deserializer
.total_calls_registered_deserializer
.deserialize::<DeserializeError>(serialized_value)
.is_ok();
}
false
}
}

pub type DeferredRegistryCallChange = SetOrDelete<DeferredCall>;
Expand Down
4 changes: 0 additions & 4 deletions massa-deferred-calls/src/macros.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
pub(crate) const DEFERRED_CALL_TOTAL_GAS: &str = "deferred_call_total_gas";

pub(crate) const DEFERRED_CALL_TOTAL_REGISTERED: &str = "deferred_call_total_registered";

pub(crate) const CALLS_TAG: u8 = 0u8;
// slot fields
pub(crate) const SLOT_TOTAL_GAS: u8 = 1u8;
Expand Down
2 changes: 1 addition & 1 deletion massa-deferred-calls/src/registry_changes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ impl Serializer<DeferredCallRegistryChanges> for DeferredRegistryChangesSerializ
pub struct DeferredRegistryChangesDeserializer {
pub(crate) u64_deserializer: U64VarIntDeserializer,
slot_changes_deserializer: DeferredRegistrySlotChangesDeserializer,
slot_deserializer: SlotDeserializer,
pub(crate) slot_deserializer: SlotDeserializer,
pub(crate) effective_total_gas_deserializer:
SetOrKeepDeserializer<u128, U128VarIntDeserializer>,
pub(crate) total_calls_registered_deserializer:
Expand Down
17 changes: 16 additions & 1 deletion massa-final-state/src/final_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use anyhow::{anyhow, Result as AnyResult};
use massa_async_pool::AsyncPool;
use massa_db_exports::{
DBBatch, MassaIteratorMode, ShareableMassaDBController, ASYNC_POOL_PREFIX,
CYCLE_HISTORY_PREFIX, DEFERRED_CREDITS_PREFIX, EXECUTED_DENUNCIATIONS_PREFIX,
CYCLE_HISTORY_PREFIX, DEFERRED_CALLS_PREFIX, DEFERRED_CALL_TOTAL_GAS,
DEFERRED_CALL_TOTAL_REGISTERED, DEFERRED_CREDITS_PREFIX, EXECUTED_DENUNCIATIONS_PREFIX,
EXECUTED_OPS_PREFIX, LEDGER_PREFIX, MIP_STORE_PREFIX, STATE_CF,
};
use massa_db_exports::{EXECUTION_TRAIL_HASH_PREFIX, MIP_STORE_STATS_PREFIX, VERSIONING_CF};
Expand Down Expand Up @@ -657,6 +658,20 @@ impl FinalState {
}
} else if serialized_key.starts_with(EXECUTION_TRAIL_HASH_PREFIX.as_bytes()) {
// no checks here as they are performed above by direct reading
} else if serialized_key.starts_with(DEFERRED_CALLS_PREFIX.as_bytes())
|| serialized_key.eq(DEFERRED_CALL_TOTAL_GAS.as_bytes())
|| serialized_key.eq(DEFERRED_CALL_TOTAL_REGISTERED.as_bytes())
{
if !self
.deferred_call_registry
.is_key_value_valid(&serialized_key, &serialized_value)
{
warn!("Wrong key/value for DEFERRED_CALLS_PREFIX serialized_key: {:?}, serialized_value: {:?}", serialized_key, serialized_value);
return Err(anyhow!(
"Wrong key/value for DEFERRED_CALLS_PREFIX serialized_key: {:?}, serialized_value: {:?}",
serialized_key, serialized_value
));
}
} else {
warn!(
"Key/value does not correspond to any prefix: serialized_key: {:?}, serialized_value: {:?}",
Expand Down
Loading