Module 0xa3::governance
use 0x1::ascii;
use 0x1::type_name;
use 0x2::address;
use 0x2::hex;
use 0x2::object;
use 0x2::package;
use 0x2::table;
use 0x2::transfer;
use 0x2::tx_context;
use 0xa0::abi;
use 0xa1::channel;
Resource Governance
struct Governance has store, key
Fields
-
id: object::UID
-
-
trusted_source_chain: ascii::String
-
-
trusted_source_address: ascii::String
-
-
message_type: u256
-
-
channel: channel::Channel
-
-
caps: table::Table<object::ID, package::UpgradeCap>
-
Constants
#[error]
const EInvalidMessageType: vector<u8> = b"invalid message type for upgrade authorization";
#[error]
const ENotNewPackage: vector<u8> = b"Not new package.";
#[error]
const ENotSelfUpgradeCap: vector<u8> = b"governance initialization requires its own upgrade capability. The provided capability belongs to a different package";
#[error]
const EUntrustedAddress: vector<u8> = b"upgrade authorization attempt from an untrusted address";
Function new
entry fun new(trusted_source_chain: ascii::String, trusted_source_address: ascii::String, message_type: u256, upgrade_cap: package::UpgradeCap, ctx: &mut tx_context::TxContext)
Implementation
entry fun new(
trusted_source_chain: String,
trusted_source_address: String,
message_type: u256,
upgrade_cap: UpgradeCap,
ctx: &mut TxContext,
) {
let package_id = object::id_from_bytes(
hex::decode(type_name::get<Governance>().get_address().into_bytes()),
);
assert!(upgrade_cap.upgrade_package() == package_id, ENotSelfUpgradeCap);
is_cap_new(&upgrade_cap);
package::make_immutable(upgrade_cap);
transfer::share_object(Governance {
id: object::new(ctx),
trusted_source_chain,
trusted_source_address,
message_type,
channel: channel::new(ctx),
caps: table::new<ID, UpgradeCap>(ctx),
})
}
Function is_governance
public fun is_governance(self: &governance::Governance, chain_name: ascii::String, addr: ascii::String): bool
Implementation
public fun is_governance(
self: &Governance,
chain_name: String,
addr: String,
): bool {
&chain_name ==
&self.trusted_source_chain &&
&addr == &self.trusted_source_address
}
Function take_upgrade_cap
entry fun take_upgrade_cap(self: &mut governance::Governance, upgrade_cap: package::UpgradeCap)
Implementation
entry fun take_upgrade_cap(self: &mut Governance, upgrade_cap: UpgradeCap) {
is_cap_new(&upgrade_cap);
self
.caps
.add(
object::id(&upgrade_cap),
upgrade_cap,
)
}
Function authorize_upgrade
public fun authorize_upgrade(self: &mut governance::Governance, approved_message: channel::ApprovedMessage): package::UpgradeTicket
Implementation
public fun authorize_upgrade(
self: &mut Governance,
approved_message: ApprovedMessage,
): UpgradeTicket {
let (source_chain, _, source_address, payload) = self
.channel
.consume_approved_message(approved_message);
assert!(
is_governance(self, source_chain, source_address),
EUntrustedAddress,
);
let mut abi = abi::new_reader(payload);
let message_type = abi.read_u256();
assert!(message_type == self.message_type, EInvalidMessageType);
let cap_id = object::id_from_address(address::from_u256(abi.read_u256()));
let policy = abi.read_u8();
let digest = abi.read_bytes();
package::authorize_upgrade(
table::borrow_mut(&mut self.caps, cap_id),
policy,
digest,
)
}
Function commit_upgrade
public fun commit_upgrade(self: &mut governance::Governance, receipt: package::UpgradeReceipt)
Implementation
public fun commit_upgrade(self: &mut Governance, receipt: UpgradeReceipt) {
package::commit_upgrade(
table::borrow_mut(
&mut self.caps,
package::receipt_cap(&receipt),
),
receipt,
)
}
Function is_cap_new
fun is_cap_new(cap: &package::UpgradeCap)
Implementation
fun is_cap_new(cap: &UpgradeCap) {
assert!(package::version(cap) == 1, ENotNewPackage);
}