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
// Copyright (c) The Diem Core Contributors
// Copyright (c) The Move Contributors
// SPDX-License-Identifier: Apache-2.0

use std::{path::PathBuf, str::FromStr};

use crate::{experimental, sandbox::utils::PackageContext, Move};
use anyhow::Result;
use move_core_types::{
    language_storage::TypeTag, parser, transaction_argument::TransactionArgument,
};
use std::path::Path;

use clap::{ArgEnum, Parser};

#[derive(Parser)]
pub enum ExperimentalCommand {
    /// Perform a read/write set analysis and print the results for
    /// `module_file`::`script_name`.
    #[clap(name = "read-write-set")]
    ReadWriteSet {
        /// Path to .mv file containing module bytecode.
        #[clap(name = "module", parse(from_os_str))]
        module_file: PathBuf,
        /// A function inside `module_file`.
        #[clap(name = "function")]
        fun_name: String,
        #[clap(
            long = "signers",
            takes_value(true),
            multiple_values(true),
            multiple_occurrences(true)
        )]
        signers: Vec<String>,
        #[clap(
            long = "args",
            parse(try_from_str = parser::parse_transaction_argument),
            takes_value(true),
            multiple_values(true),
            multiple_occurrences(true)
        )]
        args: Vec<TransactionArgument>,
        #[clap(
            long = "type-args",
            parse(try_from_str = parser::parse_type_tag),
            takes_value(true),
            multiple_values(true),
            multiple_occurrences(true)
        )]
        type_args: Vec<TypeTag>,
        #[clap(long = "concretize", possible_values = ConcretizeMode::variants(), ignore_case = true, default_value = "dont")]
        concretize: ConcretizeMode,
    },
}

// Specify if/how the analysis should concretize and filter the static analysis summary

// Specify if/how the analysis should concretize and filter the static analysis summary
#[derive(Debug, Clone, Copy, ArgEnum)]
pub enum ConcretizeMode {
    // Show the full concretized access paths read or written (e.g. 0xA/0x1::M::S/f/g)
    Paths,
    // Show only the concrete resource keys that are read (e.g. 0xA/0x1::M::S)
    Reads,
    // Show only the concrete resource keys that are written (e.g. 0xA/0x1::M::S)
    Writes,
    // Do not concretize; show the results from the static analysis
    Dont,
}

impl FromStr for ConcretizeMode {
    type Err = anyhow::Error;

    fn from_str(s: &str) -> Result<Self> {
        match s {
            "paths" => Ok(ConcretizeMode::Paths),
            "reads" => Ok(ConcretizeMode::Reads),
            "writes" => Ok(ConcretizeMode::Writes),
            "dont" => Ok(ConcretizeMode::Dont),
            _ => Err(anyhow::anyhow!("Invalid concretize mode: {}", s)),
        }
    }
}

impl ConcretizeMode {
    fn variants() -> [&'static str; 4] {
        ["paths", "reads", "writes", "dont"]
    }
}

impl ExperimentalCommand {
    pub fn handle_command(&self, move_args: &Move, storage_dir: &Path) -> Result<()> {
        match self {
            ExperimentalCommand::ReadWriteSet {
                module_file,
                fun_name,
                signers,
                args,
                type_args,
                concretize,
            } => {
                let state = PackageContext::new(&move_args.package_path, &move_args.build_config)?
                    .prepare_state(storage_dir)?;
                experimental::commands::analyze_read_write_set(
                    &state,
                    module_file,
                    fun_name,
                    signers,
                    args,
                    type_args,
                    *concretize,
                    move_args.verbose,
                )
            }
        }
    }
}