Skip to main content
Glama

MCP RAG Server

package.move11.8 kB
// Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 /// Functions for operating on Move packages from within Move: /// - Creating proof-of-publish objects from one-time witnesses /// - Administering package upgrades through upgrade policies. module sui::package { use sui::object::{Self, ID, UID}; use sui::tx_context::{TxContext, sender}; use std::ascii::String; use std::type_name; use sui::types; /// Tried to create a `Publisher` using a type that isn't a /// one-time witness. const ENotOneTimeWitness: u64 = 0; /// Tried to set a less restrictive policy than currently in place. const ETooPermissive: u64 = 1; /// This `UpgradeCap` has already authorized a pending upgrade. const EAlreadyAuthorized: u64 = 2; /// This `UpgradeCap` has not authorized an upgrade. const ENotAuthorized: u64 = 3; /// Trying to commit an upgrade to the wrong `UpgradeCap`. const EWrongUpgradeCap: u64 = 4; /// Update any part of the package (function implementations, add new /// functions or types, change dependencies) const COMPATIBLE: u8 = 0; /// Add new functions or types, or change dependencies, existing /// functions can't change. const ADDITIVE: u8 = 128; /// Only be able to change dependencies. const DEP_ONLY: u8 = 192; /// This type can only be created in the transaction that /// generates a module, by consuming its one-time witness, so it /// can be used to identify the address that published the package /// a type originated from. struct Publisher has key, store { id: UID, package: String, module_name: String, } /// Capability controlling the ability to upgrade a package. struct UpgradeCap has key, store { id: UID, /// (Mutable) ID of the package that can be upgraded. package: ID, /// (Mutable) The number of upgrades that have been applied /// successively to the original package. Initially 0. version: u64, /// What kind of upgrades are allowed. policy: u8, } /// Permission to perform a particular upgrade (for a fixed version of /// the package, bytecode to upgrade with and transitive dependencies to /// depend against). /// /// An `UpgradeCap` can only issue one ticket at a time, to prevent races /// between concurrent updates or a change in its upgrade policy after /// issuing a ticket, so the ticket is a "Hot Potato" to preserve forward /// progress. struct UpgradeTicket { /// (Immutable) ID of the `UpgradeCap` this originated from. cap: ID, /// (Immutable) ID of the package that can be upgraded. package: ID, /// (Immutable) The policy regarding what kind of upgrade this ticket /// permits. policy: u8, /// (Immutable) SHA256 digest of the bytecode and transitive /// dependencies that will be used in the upgrade. digest: vector<u8>, } /// Issued as a result of a successful upgrade, containing the /// information to be used to update the `UpgradeCap`. This is a "Hot /// Potato" to ensure that it is used to update its `UpgradeCap` before /// the end of the transaction that performed the upgrade. struct UpgradeReceipt { /// (Immutable) ID of the `UpgradeCap` this originated from. cap: ID, /// (Immutable) ID of the package after it was upgraded. package: ID, } /// Claim a Publisher object. /// Requires a One-Time-Witness to prove ownership. Due to this /// constraint there can be only one Publisher object per module /// but multiple per package (!). public fun claim<OTW: drop>(otw: OTW, ctx: &mut TxContext): Publisher { assert!(types::is_one_time_witness(&otw), ENotOneTimeWitness); let type = type_name::get_with_original_ids<OTW>(); Publisher { id: object::new(ctx), package: type_name::get_address(&type), module_name: type_name::get_module(&type), } } #[lint_allow(self_transfer)] /// Claim a Publisher object and send it to transaction sender. /// Since this function can only be called in the module initializer, /// the sender is the publisher. public fun claim_and_keep<OTW: drop>(otw: OTW, ctx: &mut TxContext) { sui::transfer::public_transfer(claim(otw, ctx), sender(ctx)) } /// Destroy a Publisher object effectively removing all privileges /// associated with it. public fun burn_publisher(self: Publisher) { let Publisher { id, package: _, module_name: _ } = self; object::delete(id); } /// Check whether type belongs to the same package as the publisher object. public fun from_package<T>(self: &Publisher): bool { let type = type_name::get_with_original_ids<T>(); (type_name::get_address(&type) == self.package) } /// Check whether a type belongs to the same module as the publisher object. public fun from_module<T>(self: &Publisher): bool { let type = type_name::get_with_original_ids<T>(); (type_name::get_address(&type) == self.package) && (type_name::get_module(&type) == self.module_name) } /// Read the name of the module. public fun published_module(self: &Publisher): &String { &self.module_name } /// Read the package address string. public fun published_package(self: &Publisher): &String { &self.package } /// The ID of the package that this cap authorizes upgrades for. /// Can be `0x0` if the cap cannot currently authorize an upgrade /// because there is already a pending upgrade in the transaction. /// Otherwise guaranteed to be the latest version of any given /// package. public fun upgrade_package(cap: &UpgradeCap): ID { cap.package } /// The most recent version of the package, increments by one for each /// successfully applied upgrade. public fun version(cap: &UpgradeCap): u64 { cap.version } /// The most permissive kind of upgrade currently supported by this /// `cap`. public fun upgrade_policy(cap: &UpgradeCap): u8 { cap.policy } /// The package that this ticket is authorized to upgrade public fun ticket_package(ticket: &UpgradeTicket): ID { ticket.package } /// The kind of upgrade that this ticket authorizes. public fun ticket_policy(ticket: &UpgradeTicket): u8 { ticket.policy } /// ID of the `UpgradeCap` that this `receipt` should be used to /// update. public fun receipt_cap(receipt: &UpgradeReceipt): ID { receipt.cap } /// ID of the package that was upgraded to: the latest version of /// the package, as of the upgrade represented by this `receipt`. public fun receipt_package(receipt: &UpgradeReceipt): ID { receipt.package } /// A hash of the package contents for the new version of the /// package. This ticket only authorizes an upgrade to a package /// that matches this digest. A package's contents are identified /// by two things: /// /// - modules: [[u8]] a list of the package's module contents /// - deps: [[u8; 32]] a list of 32 byte ObjectIDs of the /// package's transitive dependencies /// /// A package's digest is calculated as: /// /// sha3_256(sort(modules ++ deps)) public fun ticket_digest(ticket: &UpgradeTicket): &vector<u8> { &ticket.digest } /// Expose the constants representing various upgrade policies public fun compatible_policy(): u8 { COMPATIBLE } public fun additive_policy(): u8 { ADDITIVE } public fun dep_only_policy(): u8 { DEP_ONLY } /// Restrict upgrades through this upgrade `cap` to just add code, or /// change dependencies. public entry fun only_additive_upgrades(cap: &mut UpgradeCap) { restrict(cap, ADDITIVE) } /// Restrict upgrades through this upgrade `cap` to just change /// dependencies. public entry fun only_dep_upgrades(cap: &mut UpgradeCap) { restrict(cap, DEP_ONLY) } /// Discard the `UpgradeCap` to make a package immutable. public entry fun make_immutable(cap: UpgradeCap) { let UpgradeCap { id, package: _, version: _, policy: _ } = cap; object::delete(id); } /// Issue a ticket authorizing an upgrade to a particular new bytecode /// (identified by its digest). A ticket will only be issued if one has /// not already been issued, and if the `policy` requested is at least as /// restrictive as the policy set out by the `cap`. /// /// The `digest` supplied and the `policy` will both be checked by /// validators when running the upgrade. I.e. the bytecode supplied in /// the upgrade must have a matching digest, and the changes relative to /// the parent package must be compatible with the policy in the ticket /// for the upgrade to succeed. public fun authorize_upgrade( cap: &mut UpgradeCap, policy: u8, digest: vector<u8> ): UpgradeTicket { let id_zero = object::id_from_address(@0x0); assert!(cap.package != id_zero, EAlreadyAuthorized); assert!(policy >= cap.policy, ETooPermissive); let package = cap.package; cap.package = id_zero; UpgradeTicket { cap: object::id(cap), package, policy, digest, } } /// Consume an `UpgradeReceipt` to update its `UpgradeCap`, finalizing /// the upgrade. public fun commit_upgrade( cap: &mut UpgradeCap, receipt: UpgradeReceipt, ) { let UpgradeReceipt { cap: cap_id, package } = receipt; assert!(object::id(cap) == cap_id, EWrongUpgradeCap); assert!(object::id_to_address(&cap.package) == @0x0, ENotAuthorized); cap.package = package; cap.version = cap.version + 1; } #[test_only] /// Test-only function to claim a Publisher object bypassing OTW check. public fun test_claim<OTW: drop>(_: OTW, ctx: &mut TxContext): Publisher { let type = type_name::get_with_original_ids<OTW>(); Publisher { id: object::new(ctx), package: type_name::get_address(&type), module_name: type_name::get_module(&type), } } #[test_only] /// Test-only function to simulate publishing a package at address /// `ID`, to create an `UpgradeCap`. public fun test_publish(package: ID, ctx: &mut TxContext): UpgradeCap { UpgradeCap { id: object::new(ctx), package, version: 1, policy: COMPATIBLE, } } #[test_only] /// Test-only function that takes the role of the actual `Upgrade` /// command, converting the ticket for the pending upgrade to a /// receipt for a completed upgrade. public fun test_upgrade(ticket: UpgradeTicket): UpgradeReceipt { let UpgradeTicket { cap, package, policy: _, digest: _ } = ticket; // Generate a fake package ID for the upgraded package by // hashing the existing package and cap ID. let data = object::id_to_bytes(&cap); std::vector::append(&mut data, object::id_to_bytes(&package)); let package = object::id_from_bytes(sui::hash::blake2b256(&data)); UpgradeReceipt { cap, package } } fun restrict(cap: &mut UpgradeCap, policy: u8) { assert!(cap.policy <= policy, ETooPermissive); cap.policy = policy; } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ProbonoBonobo/sui-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server