This module defines a struct storing the publishing policies for the VM.
- Struct
DiemTransactionPublishingOption
- Constants
- Function
initialize
- Function
is_script_allowed
- Function
is_module_allowed
- Function
add_to_script_allow_list
- Function
set_open_script
- Function
set_open_module
- Module Specification
use 0x1::DiemConfig;
use 0x1::DiemTimestamp;
use 0x1::Errors;
use 0x1::Roles;
use 0x1::Vector;
Defines and holds the publishing policies for the VM. There are three possible configurations:
- No module publishing, only allow-listed scripts are allowed.
- No module publishing, custom scripts are allowed.
- Both module publishing and custom scripts are allowed. We represent these as the following resource.
Fields
-
script_allow_list: vector<vector<u8>>
- Only script hashes in the following list can be executed by the network. If the vector is empty, no limitation would be enforced.
-
module_publishing_allowed: bool
- Anyone can publish new module if this flag is set to true.
The script hash already exists in the allowlist
const EALLOWLIST_ALREADY_CONTAINS_SCRIPT: u64 = 1;
The script hash has an invalid length
const EINVALID_SCRIPT_HASH: u64 = 0;
const SCRIPT_HASH_LENGTH: u64 = 32;
public fun initialize(dr_account: &signer, script_allow_list: vector<vector<u8>>, module_publishing_allowed: bool)
Implementation
public fun initialize(
dr_account: &signer,
script_allow_list: vector<vector<u8>>,
module_publishing_allowed: bool,
) {
DiemTimestamp::assert_genesis();
Roles::assert_diem_root(dr_account);
DiemConfig::publish_new_config(
dr_account,
DiemTransactionPublishingOption {
script_allow_list, module_publishing_allowed
}
);
}
Specification
Must abort if the signer does not have the DiemRoot role [H11].
include Roles::AbortsIfNotDiemRoot{account: dr_account};
include DiemTimestamp::AbortsIfNotGenesis;
include DiemConfig::PublishNewConfigAbortsIf<DiemTransactionPublishingOption>;
include DiemConfig::PublishNewConfigEnsures<DiemTransactionPublishingOption> {
payload: DiemTransactionPublishingOption {
script_allow_list, module_publishing_allowed
}};
Check if sender can execute script with hash
public fun is_script_allowed(account: &signer, hash: &vector<u8>): bool
Implementation
public fun is_script_allowed(account: &signer, hash: &vector<u8>): bool {
let publish_option = DiemConfig::get<DiemTransactionPublishingOption>();
Vector::is_empty(&publish_option.script_allow_list)
|| Vector::contains(&publish_option.script_allow_list, hash)
|| Roles::has_diem_root_role(account)
}
Specification
schema AbortsIfNoTransactionPublishingOption {
include DiemTimestamp::is_genesis() ==> DiemConfig::AbortsIfNotPublished<DiemTransactionPublishingOption>{};
}
Check if a sender can publish a module
public fun is_module_allowed(account: &signer): bool
Implementation
public fun is_module_allowed(account: &signer): bool {
let publish_option = DiemConfig::get<DiemTransactionPublishingOption>();
publish_option.module_publishing_allowed || Roles::has_diem_root_role(account)
}
Specification
Add new_hash
to the list of script hashes that is allowed to be executed by the network.
public fun add_to_script_allow_list(dr_account: &signer, new_hash: vector<u8>)
Implementation
public fun add_to_script_allow_list(dr_account: &signer, new_hash: vector<u8>) {
Roles::assert_diem_root(dr_account);
assert(Vector::length(&new_hash) == SCRIPT_HASH_LENGTH, Errors::invalid_argument(EINVALID_SCRIPT_HASH));
let publish_option = DiemConfig::get<DiemTransactionPublishingOption>();
if (Vector::contains(&publish_option.script_allow_list, &new_hash)) {
abort Errors::invalid_argument(EALLOWLIST_ALREADY_CONTAINS_SCRIPT)
};
Vector::push_back(&mut publish_option.script_allow_list, new_hash);
DiemConfig::set<DiemTransactionPublishingOption>(dr_account, publish_option);
}
Specification
Must abort if the signer does not have the DiemRoot role [H11].
include Roles::AbortsIfNotDiemRoot{account: dr_account};
let allow_list = DiemConfig::get<DiemTransactionPublishingOption>().script_allow_list;
aborts_if Vector::length(new_hash) != SCRIPT_HASH_LENGTH with Errors::INVALID_ARGUMENT;
aborts_if Vector::spec_contains(allow_list, new_hash) with Errors::INVALID_ARGUMENT;
include DiemConfig::AbortsIfNotPublished<DiemTransactionPublishingOption>;
include DiemConfig::SetAbortsIf<DiemTransactionPublishingOption>{account: dr_account};
Allow the execution of arbitrary script or not.
public fun set_open_script(dr_account: &signer)
Implementation
public fun set_open_script(dr_account: &signer) {
Roles::assert_diem_root(dr_account);
let publish_option = DiemConfig::get<DiemTransactionPublishingOption>();
publish_option.script_allow_list = Vector::empty();
DiemConfig::set<DiemTransactionPublishingOption>(dr_account, publish_option);
}
Specification
Must abort if the signer does not have the DiemRoot role [H11].
include Roles::AbortsIfNotDiemRoot{account: dr_account};
include DiemConfig::AbortsIfNotPublished<DiemTransactionPublishingOption>;
include DiemConfig::SetAbortsIf<DiemTransactionPublishingOption>{account: dr_account};
Allow module publishing from arbitrary sender or not.
public fun set_open_module(dr_account: &signer, open_module: bool)
Implementation
public fun set_open_module(dr_account: &signer, open_module: bool) {
Roles::assert_diem_root(dr_account);
let publish_option = DiemConfig::get<DiemTransactionPublishingOption>();
publish_option.module_publishing_allowed = open_module;
DiemConfig::set<DiemTransactionPublishingOption>(dr_account, publish_option);
}
Specification
Must abort if the signer does not have the DiemRoot role [H11].
include Roles::AbortsIfNotDiemRoot{account: dr_account};
include DiemConfig::AbortsIfNotPublished<DiemTransactionPublishingOption>;
include DiemConfig::SetAbortsIf<DiemTransactionPublishingOption>{account: dr_account};
invariant [global] DiemTimestamp::is_operating() ==>
DiemConfig::spec_is_published<DiemTransactionPublishingOption>();
Only add_to_script_allow_list
, set_open_script
, and set_open_module
can modify the
DiemTransactionPublishingOption config [H11]
schema DiemVersionRemainsSame {
ensures old(DiemConfig::spec_is_published<DiemTransactionPublishingOption>()) ==>
global<DiemConfig<DiemTransactionPublishingOption>>(CoreAddresses::DIEM_ROOT_ADDRESS()) ==
old(global<DiemConfig<DiemTransactionPublishingOption>>(CoreAddresses::DIEM_ROOT_ADDRESS()));
}
apply DiemVersionRemainsSame to * except add_to_script_allow_list, set_open_script, set_open_module;
define spec_is_script_allowed(account: signer, hash: vector<u8>): bool {
let publish_option = DiemConfig::spec_get_config<DiemTransactionPublishingOption>();
Vector::is_empty(publish_option.script_allow_list)
|| Vector::spec_contains(publish_option.script_allow_list, hash)
|| Roles::has_diem_root_role(account)
}
define spec_is_module_allowed(account: signer): bool {
let publish_option = DiemConfig::spec_get_config<DiemTransactionPublishingOption>();
publish_option.module_publishing_allowed || Roles::has_diem_root_role(account)
}