Skip to content

Commit

Permalink
[Sui Framework] Better types and API's in ID module
Browse files Browse the repository at this point in the history
Big cleanup of the ID module that should hopefully help with usability.

- Get rid of `IDBytes`, which is not very intuitive. The equivalent type is now called `ID`.
- Rename functions for getting `ID`'s or a `vector<u8>` encoding of an ID from an object. These are likely to be the most commonly used, so tried to give them concise names and sensible type signatures.
- Introduce abort code for `new_from_bytes`
- Hid functions that let the programmer read the `version` of the object
- Hid functions that let the programmer see that an ID is encoded as an `address` under the hood. We may want the flexibility to change this.
- Introduce a `UniqueID` type to represent a globally unique ID. This isn't currently exposed to users and is technically redundant (i.e., could replace it with `ID` without any consequences), but keeping it to preserve the conceptual distinction between (1) unprivileged ID's that can be constructed by anyone, (2) privileged ID's that are guaranteed to be globally unique, (3) privileged versioned ID's. (2) may be useful in the future.
- Lot of doc comments and general reorg.
  • Loading branch information
sblackshear committed Feb 27, 2022
1 parent 1168b64 commit 9e81cd8
Show file tree
Hide file tree
Showing 19 changed files with 246 additions and 148 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Examples::TicTacToe {
use Std::Option::{Self, Option};
use Std::Vector;

use Sui::ID::{Self, VersionedID, IDBytes};
use Sui::ID::{Self, ID, VersionedID};
use Sui::Event;
use Sui::Transfer;
use Sui::TxContext::{Self, TxContext};
Expand All @@ -28,7 +28,7 @@ module Examples::TicTacToe {

struct MarkMintCap has key {
id: VersionedID,
game_id: IDBytes,
game_id: ID,
remaining_supply: u8,
}

Expand All @@ -45,22 +45,22 @@ module Examples::TicTacToe {

struct MarkSentEvent has copy, drop {
// The Object ID of the game object
game_id: IDBytes,
game_id: ID,
// The object ID of the mark sent
mark_id: IDBytes,
mark_id: ID,
}

struct GameEndEvent has copy, drop {
// The Object ID of the game object
game_id: IDBytes,
game_id: ID,
}

/// `x_address` and `o_address` are the account address of the two players.
public fun create_game(x_address: address, o_address: address, ctx: &mut TxContext) {
// TODO: Validate sender address, only GameAdmin can create games.

let id = TxContext::new_id(ctx);
let game_id_bytes = *ID::get_inner(&id);
let game_id = *ID::inner(&id);
let gameboard = vector[
vector[Option::none(), Option::none(), Option::none()],
vector[Option::none(), Option::none(), Option::none()],
Expand All @@ -77,13 +77,13 @@ module Examples::TicTacToe {
Transfer::transfer(game, TxContext::get_signer_address(ctx));
let cap = MarkMintCap {
id: TxContext::new_id(ctx),
game_id: copy game_id_bytes,
game_id: copy game_id,
remaining_supply: 5,
};
Transfer::transfer(cap, x_address);
let cap = MarkMintCap {
id: TxContext::new_id(ctx),
game_id: game_id_bytes,
game_id,
remaining_supply: 5,
};
Transfer::transfer(cap, o_address);
Expand All @@ -100,7 +100,7 @@ module Examples::TicTacToe {
// The game server will then call `place_mark` to place this mark.
Event::emit(MarkSentEvent {
game_id: *&cap.game_id,
mark_id: *ID::get_id_bytes(&mark),
mark_id: *ID::inner(&mark.id),
});
Transfer::transfer(mark, game_address);
}
Expand All @@ -126,7 +126,7 @@ module Examples::TicTacToe {

if (game.game_status != IN_PROGRESS) {
// Notify the server that the game ended so that it can delete the game.
Event::emit(GameEndEvent { game_id: *ID::get_id_bytes(game) });
Event::emit(GameEndEvent { game_id: *ID::inner(&game.id) });
if (game.game_status == X_WIN) {
Transfer::transfer( Trophy { id: TxContext::new_id(ctx) }, *&game.x_address);
} else if (game.game_status == O_WIN) {
Expand Down
2 changes: 1 addition & 1 deletion sui_core/src/unit_tests/authority_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ async fn test_handle_move_transaction() {

// Check that gas is properly deducted.
// If the number changes, we want to verify that the change is intended.
let gas_cost = 53;
let gas_cost = 54;
let gas_payment_object = authority_state
.get_object(&gas_payment_object_id)
.await
Expand Down
10 changes: 5 additions & 5 deletions sui_core/src/unit_tests/data/hero/sources/Hero.move
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Examples::Hero {
use Examples::TrustedCoin::EXAMPLE;
use Sui::Coin::{Self, Coin};
use Sui::Event;
use Sui::ID::{Self, VersionedID, IDBytes};
use Sui::ID::{Self, ID, VersionedID};
use Sui::Math;
use Sui::Transfer;
use Sui::TxContext::{Self, TxContext};
Expand Down Expand Up @@ -61,9 +61,9 @@ module Examples::Hero {
/// Address of the user that slayed the boar
slayer_address: address,
/// ID of the Hero that slayed the boar
hero: IDBytes,
hero: ID,
/// ID of the now-deceased boar
boar: IDBytes,
boar: ID,
}

/// Address of the admin account that receives payment for swords
Expand Down Expand Up @@ -137,8 +137,8 @@ module Examples::Hero {
// let the world know about the hero's triumph by emitting an event!
Event::emit(BoarSlainEvent {
slayer_address: TxContext::get_signer_address(ctx),
hero: *ID::get_inner(&hero.id),
boar: *ID::get_inner(&boar_id),
hero: *ID::inner(&hero.id),
boar: *ID::inner(&boar_id),
});
ID::delete(boar_id);

Expand Down
10 changes: 5 additions & 5 deletions sui_programmability/examples/sources/Hero.move
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Examples::Hero {
use Examples::TrustedCoin::EXAMPLE;
use Sui::Coin::{Self, Coin};
use Sui::Event;
use Sui::ID::{Self, VersionedID, IDBytes};
use Sui::ID::{Self, ID, VersionedID};
use Sui::Math;
use Sui::Transfer;
use Sui::TxContext::{Self, TxContext};
Expand Down Expand Up @@ -61,9 +61,9 @@ module Examples::Hero {
/// Address of the user that slayed the boar
slayer_address: address,
/// ID of the Hero that slayed the boar
hero: IDBytes,
hero: ID,
/// ID of the now-deceased boar
boar: IDBytes,
boar: ID,
}

/// Address of the admin account that receives payment for swords
Expand Down Expand Up @@ -137,8 +137,8 @@ module Examples::Hero {
// let the world know about the hero's triumph by emitting an event!
Event::emit(BoarSlainEvent {
slayer_address: TxContext::get_signer_address(ctx),
hero: *ID::get_inner(&hero.id),
boar: *ID::get_inner(&boar_id),
hero: *ID::inner(&hero.id),
boar: *ID::inner(&boar_id),
});
ID::delete(boar_id);

Expand Down
20 changes: 10 additions & 10 deletions sui_programmability/examples/sources/TicTacToe.move
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Examples::TicTacToe {
use Std::Option::{Self, Option};
use Std::Vector;

use Sui::ID::{Self, VersionedID, IDBytes};
use Sui::ID::{Self, ID, VersionedID};
use Sui::Event;
use Sui::Transfer;
use Sui::TxContext::{Self, TxContext};
Expand All @@ -28,7 +28,7 @@ module Examples::TicTacToe {

struct MarkMintCap has key {
id: VersionedID,
game_id: IDBytes,
game_id: ID,
remaining_supply: u8,
}

Expand All @@ -45,22 +45,22 @@ module Examples::TicTacToe {

struct MarkSentEvent has copy, drop {
// The Object ID of the game object
game_id: IDBytes,
game_id: ID,
// The object ID of the mark sent
mark_id: IDBytes,
mark_id: ID,
}

struct GameEndEvent has copy, drop {
// The Object ID of the game object
game_id: IDBytes,
game_id: ID,
}

/// `x_address` and `o_address` are the account address of the two players.
public fun create_game(x_address: address, o_address: address, ctx: &mut TxContext) {
// TODO: Validate sender address, only GameAdmin can create games.

let id = TxContext::new_id(ctx);
let game_id_bytes = *ID::get_inner(&id);
let game_id = *ID::inner(&id);
let gameboard = vector[
vector[Option::none(), Option::none(), Option::none()],
vector[Option::none(), Option::none(), Option::none()],
Expand All @@ -77,13 +77,13 @@ module Examples::TicTacToe {
Transfer::transfer(game, TxContext::get_signer_address(ctx));
let cap = MarkMintCap {
id: TxContext::new_id(ctx),
game_id: copy game_id_bytes,
game_id: copy game_id,
remaining_supply: 5,
};
Transfer::transfer(cap, x_address);
let cap = MarkMintCap {
id: TxContext::new_id(ctx),
game_id: game_id_bytes,
game_id,
remaining_supply: 5,
};
Transfer::transfer(cap, o_address);
Expand All @@ -100,7 +100,7 @@ module Examples::TicTacToe {
// The game server will then call `place_mark` to place this mark.
Event::emit(MarkSentEvent {
game_id: *&cap.game_id,
mark_id: *ID::get_id_bytes(&mark),
mark_id: *ID::inner(&mark.id),
});
Transfer::transfer(mark, game_address);
}
Expand All @@ -126,7 +126,7 @@ module Examples::TicTacToe {

if (game.game_status != IN_PROGRESS) {
// Notify the server that the game ended so that it can delete the game.
Event::emit(GameEndEvent { game_id: *ID::get_id_bytes(game) });
Event::emit(GameEndEvent { game_id: *ID::inner(&game.id) });
if (game.game_status == X_WIN) {
Transfer::transfer( Trophy { id: TxContext::new_id(ctx) }, *&game.x_address);
} else if (game.game_status == O_WIN) {
Expand Down
22 changes: 11 additions & 11 deletions sui_programmability/framework/sources/Collection.move
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Sui::Collection {
use Std::Errors;
use Std::Option::{Self, Option};
use Std::Vector::Self;
use Sui::ID::{Self, VersionedID, IDBytes};
use Sui::ID::{Self, ID, VersionedID};
use Sui::Transfer;
use Sui::TxContext::{Self, TxContext};

Expand All @@ -17,7 +17,7 @@ module Sui::Collection {

struct Collection has key {
id: VersionedID,
objects: vector<IDBytes>,
objects: vector<ID>,
max_capacity: u64,
}

Expand All @@ -34,7 +34,7 @@ module Sui::Collection {
);
Collection {
id: TxContext::new_id(ctx),
objects: Vector::empty<IDBytes>(),
objects: Vector::empty(),
max_capacity,
}
}
Expand All @@ -56,24 +56,24 @@ module Sui::Collection {
size(c) + 1 <= c.max_capacity,
Errors::limit_exceeded(EMAX_CAPACITY_EXCEEDED)
);
let id_bytes = ID::get_id_bytes(&object);
if (contains(c, id_bytes)) {
let id = ID::id(&object);
if (contains(c, id)) {
abort EOBJECT_DOUBLE_ADD
};
Vector::push_back(&mut c.objects, *id_bytes);
Vector::push_back(&mut c.objects, *id);
Transfer::transfer_to_object(object, c);
}

/// Check whether the collection contains a specific object,
/// identified by the object id in bytes.
public fun contains(c: &Collection, id_bytes: &IDBytes): bool {
Option::is_some(&find(c, id_bytes))
public fun contains(c: &Collection, id: &ID): bool {
Option::is_some(&find(c, id))
}

/// Remove and return the object from the collection.
/// Abort if the object is not found.
public fun remove<T: key>(c: &mut Collection, object: T): T {
let idx = find(c, ID::get_id_bytes(&object));
let idx = find(c, ID::id(&object));
if (Option::is_none(&idx)) {
abort EOBJECT_DOUBLE_ADD
};
Expand All @@ -100,11 +100,11 @@ module Sui::Collection {

/// Look for the object identified by `id_bytes` in the collection.
/// Returns the index if found, none if not found.
fun find(c: &Collection, id_bytes: &IDBytes): Option<u64> {
fun find(c: &Collection, id: &ID): Option<u64> {
let i = 0;
let len = size(c);
while (i < len) {
if (Vector::borrow(&c.objects, i) == id_bytes) {
if (Vector::borrow(&c.objects, i) == id) {
return Option::some(i)
};
i = i + 1;
Expand Down
10 changes: 5 additions & 5 deletions sui_programmability/framework/sources/Escrow.move
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/// trusts a third party for liveness, but not
/// safety.
module Sui::Escrow {
use Sui::ID::{Self, IDBytes, VersionedID};
use Sui::ID::{Self, ID, VersionedID};
use Sui::Transfer;
use Sui::TxContext::{Self, TxContext};

Expand All @@ -17,7 +17,7 @@ module Sui::Escrow {
// TODO: this is probably a bad idea if the object is mutable.
// that can be fixed by asking for an additional approval
// from `sender`, but let's keep it simple for now.
exchange_for: IDBytes,
exchange_for: ID,
/// the escrowed object
escrowed: T,
}
Expand All @@ -31,7 +31,7 @@ module Sui::Escrow {
public fun create<T: key + store, ExchangeForT: key + store>(
recipient: address,
third_party: address,
exchange_for: IDBytes,
exchange_for: ID,
escrowed: T,
ctx: &mut TxContext
) {
Expand Down Expand Up @@ -70,8 +70,8 @@ module Sui::Escrow {
assert!(&sender1 == &recipient2, ETODO);
assert!(&sender2 == &recipient1, ETODO);
// check object ID compatibility
assert!(ID::get_id_bytes(&escrowed1) == &exchange_for2, ETODO);
assert!(ID::get_id_bytes(&escrowed2) == &exchange_for1, ETODO);
assert!(ID::id(&escrowed1) == &exchange_for2, ETODO);
assert!(ID::id(&escrowed2) == &exchange_for1, ETODO);
// everything matches. do the swap!
Transfer::transfer(escrowed1, sender2);
Transfer::transfer(escrowed2, sender1)
Expand Down
9 changes: 5 additions & 4 deletions sui_programmability/framework/sources/Geniteam.move
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module Sui::Geniteam {
use Sui::ID::{Self, VersionedID, IDBytes};
use Sui::ID::{Self, ID, VersionedID};
use Sui::TxContext::{Self, TxContext};
use Sui::Transfer;
use Std::ASCII::{Self, String};
Expand Down Expand Up @@ -119,13 +119,13 @@ module Sui::Geniteam {

/// Remove a monster from a farm.
/// Aborts if the monster with the given ID is not found
public fun remove_monster_(self: &mut Farm, monster_id: &IDBytes): Monster {
public fun remove_monster_(self: &mut Farm, monster_id: &ID): Monster {
let monsters = &mut self.pet_monsters;
let num_monsters = Vector::length(monsters);
let i = 0;
while (i < num_monsters) {
let m = Vector::borrow(monsters, i);
if (ID::get_inner(&m.id) == monster_id) {
if (ID::id(m) == monster_id) {
break
};
i = i + 1;
Expand Down Expand Up @@ -190,7 +190,8 @@ module Sui::Geniteam {

/// Remove a monster from a farm amd transfer it to the transaction sender
public fun remove_monster(self: &mut Farm, monster_id: vector<u8>, ctx: &mut TxContext) {
let monster = remove_monster_(self, &ID::new_bytes(monster_id));
// TODO: monster_id should be probably be `address`, but leaving this as-is to avoid breaking Geniteam
let monster = remove_monster_(self, &ID::new_from_bytes(monster_id));
Transfer::transfer(monster, TxContext::get_signer_address(ctx))
}

Expand Down
Loading

0 comments on commit 9e81cd8

Please sign in to comment.