Skip to content

Commit

Permalink
authority(visitor): avoid fully deserializing dynamic field (#19548)
Browse files Browse the repository at this point in the history
## Description

Make it so that deserializing dynamic field info does not inflate the
whole field -- just the outer struct -- which in turn means that this
operation cannot fail.

## Test plan

```
sui-core$ cargo simtest
sui-adapter-transactional-tests$ cargo simtest
```

## Stack

- #19517 
- #19518 
- #19519 
- #19520 
- #19521 

---

## Release notes

Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.

For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.

- [ ] Protocol: 
- [ ] Nodes (Validators and Full nodes): 
- [ ] Indexer: 
- [ ] JSON-RPC: 
- [ ] GraphQL: 
- [ ] CLI: 
- [ ] Rust SDK:
- [ ] REST API:
  • Loading branch information
amnn authored Sep 30, 2024
1 parent a397bcf commit ba30aba
Showing 1 changed file with 43 additions and 24 deletions.
67 changes: 43 additions & 24 deletions crates/sui-core/src/authority.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ use std::{
use sui_config::node::{AuthorityOverloadConfig, StateDebugDumpConfig};
use sui_config::NodeConfig;
use sui_types::crypto::RandomnessRound;
use sui_types::dynamic_field::visitor as DFV;
use sui_types::execution_status::ExecutionStatus;
use sui_types::inner_temporary_store::PackageStoreWithFallback;
use sui_types::layout_resolver::into_struct_layout;
use sui_types::layout_resolver::LayoutResolver;
use sui_types::messages_consensus::{AuthorityCapabilitiesV1, AuthorityCapabilitiesV2};
use sui_types::object::bounded_visitor::BoundedVisitor;
use tap::{TapFallible, TapOptional};
use tokio::sync::mpsc::unbounded_channel;
use tokio::sync::{mpsc, oneshot, RwLock};
Expand Down Expand Up @@ -83,7 +85,7 @@ use sui_types::crypto::{default_hash, AuthoritySignInfo, Signer};
use sui_types::deny_list_v1::check_coin_deny_list_v1;
use sui_types::digests::ChainIdentifier;
use sui_types::digests::TransactionEventsDigest;
use sui_types::dynamic_field::{DynamicFieldInfo, DynamicFieldName, DynamicFieldType};
use sui_types::dynamic_field::{DynamicFieldInfo, DynamicFieldName};
use sui_types::effects::{
InputSharedObject, SignedTransactionEffects, TransactionEffects, TransactionEffectsAPI,
TransactionEvents, VerifiedCertifiedTransactionEffects, VerifiedSignedTransactionEffects,
Expand Down Expand Up @@ -2381,34 +2383,59 @@ impl AuthorityState {
let Some(move_object) = o.data.try_as_move().cloned() else {
return Ok(None);
};

// We only index dynamic field objects
if !move_object.type_().is_dynamic_field() {
return Ok(None);
}

let layout = into_struct_layout(
resolver.get_annotated_layout(&move_object.type_().clone().into())?,
)?;
let move_struct = move_object.to_move_struct(&layout)?;
let layout = resolver
.get_annotated_layout(&move_object.type_().clone().into())?
.into_layout();

let (name_value, type_, object_id) =
DynamicFieldInfo::parse_move_object(&move_struct).tap_err(|e| warn!("{e}"))?;
let field =
DFV::FieldVisitor::deserialize(move_object.contents(), &layout).map_err(|e| {
SuiError::ObjectDeserializationError {
error: e.to_string(),
}
})?;

let name_type = move_object.type_().try_extract_field_name(&type_)?;
let type_ = field.kind;
let name_type: TypeTag = field.name_layout.into();
let bcs_name = field.name_bytes.to_owned();

let bcs_name = bcs::to_bytes(&name_value.clone().undecorate()).map_err(|e| {
SuiError::ObjectSerializationError {
error: format!("{e}"),
}
})?;
let name_value = BoundedVisitor::deserialize_value(field.name_bytes, field.name_layout)
.map_err(|e| {
warn!("{e}");
SuiError::ObjectDeserializationError {
error: e.to_string(),
}
})?;

let name = DynamicFieldName {
type_: name_type,
value: SuiMoveValue::from(name_value).to_json_value(),
};

Ok(Some(match type_ {
DynamicFieldType::DynamicObject => {
let value_metadata = field.value_metadata().map_err(|e| {
warn!("{e}");
SuiError::ObjectDeserializationError {
error: e.to_string(),
}
})?;

Ok(Some(match value_metadata {
DFV::ValueMetadata::DynamicField(object_type) => DynamicFieldInfo {
name,
bcs_name,
type_,
object_type: object_type.to_canonical_string(/* with_prefix */ true),
object_id: o.id(),
version: o.version(),
digest: o.digest(),
},

DFV::ValueMetadata::DynamicObjectField(object_id) => {
// Find the actual object from storage using the object id obtained from the wrapper.

// Try to find the object in the written objects first.
Expand All @@ -2431,6 +2458,7 @@ impl AuthorityState {
let object_type = object.data.type_().unwrap().clone();
(version, digest, object_type)
};

DynamicFieldInfo {
name,
bcs_name,
Expand All @@ -2441,15 +2469,6 @@ impl AuthorityState {
digest,
}
}
DynamicFieldType::DynamicField { .. } => DynamicFieldInfo {
name,
bcs_name,
type_,
object_type: move_object.into_type().into_type_params()[1].to_string(),
object_id: o.id(),
version: o.version(),
digest: o.digest(),
},
}))
}

Expand Down

0 comments on commit ba30aba

Please sign in to comment.