Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,12 @@ If you wish to validate DVFs that have not been signed, you can add the `--allow
dv validate --allowuntrusted new.dvf.json
```

By default, `dv` stops execution after the first validation error has been found. By passing the flag `--continue`, `dv` will output all validation errors:

```
dv validate --continue new.dvf.json
```

### Update DVF

**Please note: The `update` command is currently only updating existing storage variables in a DVF and might not be suitable for fully updating a DVF to the current state of a smart contract. This behavior will be changed in future releases.**
Expand Down
47 changes: 41 additions & 6 deletions src/dvf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,18 +69,21 @@ fn aggregate_results(
Ok(())
}

#[allow(clippy::too_many_arguments)]
fn validate_dvf(
config: &DVFConfig,
input_file: &Path,
validation_block_num: u64,
registry: &Registry,
seen_ids: &mut HashSet<String>,
allow_untrusted: bool,
continue_on_mismatch: bool,
expected_contract_name: Option<String>,
) -> Result<(), ValidationError> {
let mut pc = 1_u64;
let progress_mode = ProgressMode::Validation;
print_progress("Consistency Checks.", &mut pc, &progress_mode);
let mut mismatch_found = false;

let filled = parse::CompleteDVF::from_path(input_file)?;

Expand Down Expand Up @@ -173,15 +176,21 @@ fn validate_dvf(
let start_index: usize = 32 - storage_variable.offset - size;
let end_index: usize = start_index + size;
if !storage_variable.compare(&current_val[start_index..end_index]) {
return Err(ValidationError::Invalid(format!(
let message = format!(
"Value mismatch for {} (slot {:#x}, offset {}).\nNew value: 0x{}\nOperator: {}\nOld value: 0x{}",
&storage_variable.var_name,
&storage_variable.slot,
&storage_variable.offset,
hex::encode(&current_val[start_index..end_index]),
&storage_variable.comparison_operator,
hex::encode(&storage_variable.value)
)));
);
if continue_on_mismatch {
mismatch_found = true;
println!("{}", message);
} else {
return Err(ValidationError::Invalid(message));
}
}
}

Expand Down Expand Up @@ -209,22 +218,40 @@ fn validate_dvf(
for i in 0..seen_events.len() {
let log_inner = &seen_events[i].inner;
if log_inner.topics() != critical_event.occurrences[i].topics {
return Err(ValidationError::Invalid(format!(
let message = format!(
"Mismatching topics for event occurrence {} of {}.",
i, critical_event.sig
)));
);
if continue_on_mismatch {
mismatch_found = true;
println!("{}", message);
} else {
return Err(ValidationError::Invalid(message));
}
}
if log_inner.data.data != critical_event.occurrences[i].data {
return Err(ValidationError::Invalid(format!(
let message = format!(
"Mismatching data for event occurrence {} of {}.",
i, critical_event.sig
)));
);
if continue_on_mismatch {
mismatch_found = true;
println!("{}", message);
} else {
return Err(ValidationError::Invalid(message));
}
}
}
pb.inc(1);
}
pb.finish_and_clear();

if mismatch_found {
return Err(ValidationError::Invalid(String::from(
"See previous mismatches.",
)));
}

// Check insecure flag
if let Some(insecure) = filled.insecure {
if insecure {
Expand Down Expand Up @@ -254,6 +281,7 @@ fn validate_dvf(
registry,
seen_ids,
allow_untrusted,
false,
Some(reference.contract_name.clone()),
));
}
Expand Down Expand Up @@ -471,6 +499,11 @@ fn main() {
.help("Allows validation of unsigned or untrusted DVFs")
.action(clap::ArgAction::SetTrue),
)
.arg(
arg!(--continue)
.help("Do not stop on the first mismatch but continue to show more")
.action(clap::ArgAction::SetTrue),
)
.arg(arg!(<DVF>).help("The DVF file").required(true)),
)
.subcommand(
Expand Down Expand Up @@ -1445,6 +1478,7 @@ fn process(matches: ArgMatches) -> Result<(), ValidationError> {

let registry = registry::Registry::from_config(&config)?;
let allow_untrusted = sub_m.get_flag("allowuntrusted");
let continue_on_mismatch = sub_m.get_flag("continue");

let validation_block_num: u64 = *sub_m
.get_one::<u64>("validationblock")
Expand All @@ -1457,6 +1491,7 @@ fn process(matches: ArgMatches) -> Result<(), ValidationError> {
&registry,
&mut HashSet::new(),
allow_untrusted,
continue_on_mismatch,
None,
) {
Ok(()) => {
Expand Down
Loading