Skip to content

Commit

Permalink
Merge branch 'RGB-WG:master' into check-attach-id
Browse files Browse the repository at this point in the history
  • Loading branch information
Jack Choi authored Jun 22, 2024
2 parents cd2ab26 + b2885ba commit 86ff555
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 4 deletions.
97 changes: 94 additions & 3 deletions src/interface/iimpl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;

Expand Down Expand Up @@ -374,13 +375,37 @@ pub enum ImplInconsistency {

/// implementation references unknown interface error '{0}'.
IfaceErrorAbsent(VariantName),

/// metadata field '{0}' is repeated {1} times
RepeatedMetaData(FieldName, i32),

/// global state field '{0}' is repeated {1} times
RepeatedGlobalState(FieldName, i32),

/// assignments field '{0}' is repeated {1} times
RepeatedAssignments(FieldName, i32),

/// valencies field '{0}' is repeated {1} times
RepeatedValencies(FieldName, i32),

/// transition field '{0}' is repeated {1} times
RepeatedTransitions(FieldName, i32),

/// extension field '{0}' is repeated {1} times
RepeatedExtensions(FieldName, i32),
}

impl IfaceImpl {
pub fn check(&self, iface: &Iface, schema: &Schema) -> Result<(), Vec<ImplInconsistency>> {
let mut errors = vec![];

let now = Utc::now();
let mut dup_metadata = HashMap::new();
let mut dup_global_state = HashMap::new();
let mut dup_assignments = HashMap::new();
let mut dup_valencies = HashMap::new();
let mut dup_transitions = HashMap::new();
let mut dup_extensions = HashMap::new();

match Utc.timestamp_opt(self.timestamp, 0).single() {
Some(ts) if ts > now => errors.push(ImplInconsistency::FutureTimestamp(ts)),
None => errors.push(ImplInconsistency::InvalidTimestamp(self.timestamp)),
Expand All @@ -393,76 +418,142 @@ impl IfaceImpl {
}
}
for field in &self.metadata {
dup_metadata
.entry(field.name.clone())
.and_modify(|counter| *counter += 1)
.or_insert(0);
if !schema.meta_types.contains_key(&field.id) {
errors.push(ImplInconsistency::SchemaMetaAbsent(field.name.clone(), field.id));
}
}

dup_metadata
.iter()
.filter(|(_, &count)| count > 1)
.for_each(|(field_name, &count)| {
errors.push(ImplInconsistency::RepeatedMetaData(field_name.clone(), count));
});

for name in iface.global_state.keys() {
if self.global_state.iter().all(|field| &field.name != name) {
errors.push(ImplInconsistency::IfaceGlobalAbsent(name.clone()));
}
}
for field in &self.global_state {
dup_global_state
.entry(field.name.clone())
.and_modify(|counter| *counter += 1)
.or_insert(0);
if !schema.global_types.contains_key(&field.id) {
errors.push(ImplInconsistency::SchemaGlobalAbsent(field.name.clone(), field.id));
}
}

dup_global_state
.iter()
.filter(|(_, &count)| count > 1)
.for_each(|(field_name, &count)| {
errors.push(ImplInconsistency::RepeatedGlobalState(field_name.clone(), count));
});

for name in iface.assignments.keys() {
if self.assignments.iter().all(|field| &field.name != name) {
errors.push(ImplInconsistency::IfaceAssignmentAbsent(name.clone()));
}
}
for field in &self.assignments {
dup_assignments
.entry(field.name.clone())
.and_modify(|counter| *counter += 1)
.or_insert(0);
if !schema.owned_types.contains_key(&field.id) {
errors
.push(ImplInconsistency::SchemaAssignmentAbsent(field.name.clone(), field.id));
}
}

dup_assignments
.iter()
.filter(|(_, &count)| count > 1)
.for_each(|(field_name, &count)| {
errors.push(ImplInconsistency::RepeatedAssignments(field_name.clone(), count));
});

for name in iface.valencies.keys() {
if self.valencies.iter().all(|field| &field.name != name) {
errors.push(ImplInconsistency::IfaceValencyAbsent(name.clone()));
}
}
for field in &self.valencies {
dup_valencies
.entry(field.name.clone())
.and_modify(|counter| *counter += 1)
.or_insert(0);

if !schema.valency_types.contains(&field.id) {
errors.push(ImplInconsistency::SchemaValencyAbsent(field.name.clone(), field.id));
}
}
dup_valencies
.iter()
.filter(|(_, &count)| count > 1)
.for_each(|(field_name, &count)| {
errors.push(ImplInconsistency::RepeatedValencies(field_name.clone(), count));
});

for name in iface.transitions.keys() {
if self.transitions.iter().all(|field| &field.name != name) {
errors.push(ImplInconsistency::IfaceTransitionAbsent(name.clone()));
}
}
for field in &self.transitions {
dup_transitions
.entry(field.name.clone())
.and_modify(|counter| *counter += 1)
.or_insert(0);

if !schema.transitions.contains_key(&field.id) {
errors
.push(ImplInconsistency::SchemaTransitionAbsent(field.name.clone(), field.id));
}
}

dup_transitions
.iter()
.filter(|(_, &count)| count > 1)
.for_each(|(field_name, &count)| {
errors.push(ImplInconsistency::RepeatedTransitions(field_name.clone(), count));
});

for name in iface.extensions.keys() {
if self.extensions.iter().all(|field| &field.name != name) {
errors.push(ImplInconsistency::IfaceExtensionAbsent(name.clone()));
}
}
for field in &self.extensions {
dup_extensions
.entry(field.name.clone())
.and_modify(|counter| *counter += 1)
.or_insert(0);

if !schema.extensions.contains_key(&field.id) {
errors.push(ImplInconsistency::SchemaExtensionAbsent(field.name.clone(), field.id));
}
}

dup_extensions
.iter()
.filter(|(_, &count)| count > 1)
.for_each(|(field_name, &count)| {
errors.push(ImplInconsistency::RepeatedExtensions(field_name.clone(), count));
});

for var in &self.errors {
if iface.errors.keys().all(|name| name != &var.name) {
errors.push(ImplInconsistency::IfaceErrorAbsent(var.name.clone()));
}
}

// TODO: Warn about repeated field names

if errors.is_empty() {
Ok(())
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/persistence/stock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ pub enum StockError<

#[from]
#[display(doc_comments)]
/// state for contract {0} is now known.
/// state for contract {0} is not known.
///
/// It may happen due to RGB standard library bug, or indicate internal
/// stash inconsistency and compromised stash data storage.
Expand Down

0 comments on commit 86ff555

Please sign in to comment.