Skip to content

Commit

Permalink
Discoverability of SuiSystemState object (MystenLabs#2027)
Browse files Browse the repository at this point in the history
  • Loading branch information
lxfind authored May 18, 2022
1 parent d5a8602 commit 219a402
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 8 deletions.
6 changes: 6 additions & 0 deletions crates/sui-types/src/base_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,12 @@ impl ObjectID {
Self::from(AccountAddress::random())
}

pub const fn from_single_byte(byte: u8) -> ObjectID {
let mut bytes = [0u8; Self::LENGTH];
bytes[Self::LENGTH - 1] = byte;
ObjectID::new(bytes)
}

/// Converts from hex string to ObjectID where the string is prefixed with 0x
/// Its okay if the strings are less than expected
pub fn from_hex_literal(literal: &str) -> Result<Self, ObjectIDParseError> {
Expand Down
7 changes: 7 additions & 0 deletions crates/sui-types/src/coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,10 @@ impl Coin {
}
}
}

// Rust version of the Move Sui::Coin::TreasuryCap type
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub struct TreasuryCap {
pub id: VersionedID,
pub total_supply: u64,
}
5 changes: 5 additions & 0 deletions crates/sui-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
rust_2021_compatibility
)]

use base_types::ObjectID;
use move_core_types::account_address::AccountAddress;

#[macro_use]
Expand All @@ -29,6 +30,7 @@ pub mod object;
pub mod signature_seed;
pub mod storage;
pub mod sui_serde;
pub mod sui_system_state;
pub mod waypoint;

#[path = "./unit_tests/utils.rs"]
Expand All @@ -42,6 +44,9 @@ pub const MOVE_STDLIB_ADDRESS: AccountAddress = AccountAddress::ONE;
/// Same as the ObjectID
pub const SUI_FRAMEWORK_ADDRESS: AccountAddress = get_hex_address_two();

/// 0x5: hardcoded object ID for the singleton sui system state object.
pub const SUI_SYSTEM_STATE_OBJECT_ID: ObjectID = ObjectID::from_single_byte(5);

const fn get_hex_address_two() -> AccountAddress {
let mut addr = [0u8; AccountAddress::LENGTH];
addr[AccountAddress::LENGTH - 1] = 2u8;
Expand Down
80 changes: 80 additions & 0 deletions crates/sui-types/src/sui_system_state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use move_core_types::{
account_address::AccountAddress, ident_str, identifier::IdentStr, language_storage::StructTag,
};
use serde::{Deserialize, Serialize};

use crate::{balance::Balance, coin::TreasuryCap, id::VersionedID, SUI_FRAMEWORK_ADDRESS};

const SUI_SYSTEM_STATE_STRUCT_NAME: &IdentStr = ident_str!("SuiSystemState");
const SUI_SYSTEM_MODULE_NAME: &IdentStr = ident_str!("SuiSystem");

/// Rust version of the Move Sui::SuiSystem::SystemParameters type
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub struct SystemParameters {
pub min_validator_stake: u64,
pub max_validator_stake: u64,
pub max_validator_candidate_count: u64,
}

/// Rust version of the Move Std::Option::Option type.
/// Putting it in this file because it's only used here.
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub struct MoveOption<T> {
pub vec: Vec<T>,
}

/// Rust version of the Move Sui::Validator::Validator type
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub struct Validator {
pub sui_address: AccountAddress,
pub pubkey_bytes: Vec<u8>,
pub name: Vec<u8>,
pub net_address: Vec<u8>,
pub stake: Balance,
pub delegation: u64,
pub pending_stake: MoveOption<Balance>,
pub pending_withdraw: u64,
pub pending_delegation: u64,
pub pending_delegation_withdraw: u64,
pub delegator_count: u64,
pub pending_delegator_count: u64,
pub pending_delegator_withdraw_count: u64,
}

/// Rust version of the Move Sui::ValidatorSet::ValidatorSet type
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub struct ValidatorSet {
pub validator_stake: u64,
pub delegation_stake: u64,
pub quorum_stake_threshold: u64,
pub active_validators: Vec<Validator>,
pub pending_validators: Vec<Validator>,
pub pending_removals: Vec<u64>,
}

/// Rust version of the Move Sui::SuiSystem::SuiSystemState type
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub struct SuiSystemState {
pub id: VersionedID,
pub epoch: u64,
pub validators: ValidatorSet,
pub treasury_cap: TreasuryCap,
pub storage_fund: Balance,
pub parameters: SystemParameters,
pub delegation_reward: Balance,
// TODO: Use getters instead of all pub.
}

impl SuiSystemState {
pub fn type_() -> StructTag {
StructTag {
address: SUI_FRAMEWORK_ADDRESS,
name: SUI_SYSTEM_STATE_STRUCT_NAME.to_owned(),
module: SUI_SYSTEM_MODULE_NAME.to_owned(),
type_params: vec![],
}
}
}
17 changes: 17 additions & 0 deletions sui_core/src/unit_tests/authority_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ use sui_types::{
crypto::{get_key_pair, Signature},
messages::Transaction,
object::{Owner, OBJECT_START_VERSION},
sui_system_state::SuiSystemState,
SUI_SYSTEM_STATE_OBJECT_ID,
};

use std::fs;
Expand Down Expand Up @@ -1227,6 +1229,21 @@ async fn test_idempotent_reversed_confirmation() {
);
}

#[tokio::test]
async fn test_genesis_sui_sysmtem_state_object() {
// This test verifies that we can read the genesis SuiSystemState object.
// And its Move layout matches the definition in Rust (so that we can deserialize it).
let authority_state = init_state().await;
let sui_system_object = authority_state
.get_object(&SUI_SYSTEM_STATE_OBJECT_ID)
.await
.unwrap()
.unwrap();
let move_object = sui_system_object.data.try_as_move().unwrap();
let _sui_system_state = bcs::from_bytes::<SuiSystemState>(move_object.contents()).unwrap();
assert_eq!(move_object.type_, SuiSystemState::type_());
}

// helpers

#[cfg(test)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module Sui::Genesis {

/// Basic information of Validator1, as an example, all dummy values.
const VALIDATOR1_SUI_ADDRESS: address = @0x1234;
const VALIDATOR1_PUBKEY_BYTES: vector<u8> = x"FF";
const VALIDATOR1_NAME: vector<u8> = b"Validator1";
const VALIDATOR1_IP_ADDRESS: vector<u8> = x"00FF00FF";
const VALIDATOR1_STAKE: u64 = 100000000000000;
Expand All @@ -38,6 +39,7 @@ module Sui::Genesis {
let validators = Vector::empty();
Vector::push_back(&mut validators, Validator::new(
VALIDATOR1_SUI_ADDRESS,
VALIDATOR1_PUBKEY_BYTES,
VALIDATOR1_NAME,
VALIDATOR1_IP_ADDRESS,
Coin::mint_balance(VALIDATOR1_STAKE, &mut treasury_cap),
Expand All @@ -49,7 +51,6 @@ module Sui::Genesis {
INIT_MAX_VALIDATOR_COUNT,
INIT_MIN_VALIDATOR_STAKE,
INIT_MAX_VALIDATOR_STAKE,
ctx,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module Sui::SuiSystem {
use Sui::Coin::{Self, Coin, TreasuryCap};
use Sui::Delegation::{Self, Delegation};
use Sui::EpochRewardRecord::{Self, EpochRewardRecord};
use Sui::ID::VersionedID;
use Sui::ID::{Self, VersionedID};
use Sui::SUI::SUI;
use Sui::Transfer;
use Sui::TxContext::{Self, TxContext};
Expand Down Expand Up @@ -60,11 +60,11 @@ module Sui::SuiSystem {
max_validator_candidate_count: u64,
min_validator_stake: u64,
max_validator_stake: u64,
ctx: &mut TxContext,
) {
assert!(min_validator_stake < max_validator_stake, 0);
let state = SuiSystemState {
id: TxContext::new_id(ctx),
// Use a hardcoded ID.
id: ID::get_sui_system_state_object_id(),
epoch: 0,
validators: ValidatorSet::new(validators),
treasury_cap,
Expand All @@ -88,6 +88,7 @@ module Sui::SuiSystem {
// someone to become a validator?
public(script) fun request_add_validator(
self: &mut SuiSystemState,
pubkey_bytes: vector<u8>,
name: vector<u8>,
net_address: vector<u8>,
stake: Coin<SUI>,
Expand All @@ -105,6 +106,7 @@ module Sui::SuiSystem {
);
let validator = Validator::new(
TxContext::sender(ctx),
pubkey_bytes,
name,
net_address,
Coin::into_balance(stake)
Expand Down
17 changes: 13 additions & 4 deletions sui_programmability/framework/sources/Governance/Validator.move
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

module Sui::Validator {
use Std::ASCII::{Self, String};
use Std::ASCII;
use Std::Option::{Self, Option};
use Std::Vector;

Expand All @@ -25,8 +25,11 @@ module Sui::Validator {
/// The Sui Address of the validator. This is the sender that created the Validator object,
/// and also the address to send validator/coins to during withdraws.
sui_address: address,
/// The public key bytes corresponding to the private key that the validator
/// holds to sign transactions. For now, this is the same as AuthorityName.
pubkey_bytes: vector<u8>,
/// A unique human-readable name of this validator.
name: String,
name: vector<u8>,
/// The network address of the validator (could also contain extra info such as port, DNS and etc.).
net_address: vector<u8>,
/// The current active stake. This will not change during an epoch. It can only
Expand Down Expand Up @@ -54,17 +57,22 @@ module Sui::Validator {

public(friend) fun new(
sui_address: address,
pubkey_bytes: vector<u8>,
name: vector<u8>,
net_address: vector<u8>,
stake: Balance<SUI>,
): Validator {
assert!(
Vector::length(&net_address) <= 100 || Vector::length(&name) <= 50,
// TODO: These constants are arbitrary, will adjust once we know more.
Vector::length(&net_address) <= 100 && Vector::length(&name) <= 50 && Vector::length(&pubkey_bytes) <= 128,
0
);
// Check that the name is human-readable.
ASCII::string(copy name);
Validator {
sui_address,
name: ASCII::string(name),
pubkey_bytes,
name,
net_address,
stake,
delegation: 0,
Expand All @@ -81,6 +89,7 @@ module Sui::Validator {
public(friend) fun destroy(self: Validator, ctx: &mut TxContext) {
let Validator {
sui_address,
pubkey_bytes: _,
name: _,
net_address: _,
stake,
Expand Down
10 changes: 10 additions & 0 deletions sui_programmability/framework/sources/ID.move
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Sui::ID {
use Std::BCS;
use Std::Vector;

friend Sui::SuiSystem;
friend Sui::Transfer;
friend Sui::TxContext;

Expand All @@ -15,6 +16,9 @@ module Sui::ID {
/// Version of an object ID created by the current transaction.
const INITIAL_VERSION: u64 = 0;

/// The hardcoded ID for the singleton Sui System State Object.
const SUI_SYSTEM_STATE_OBJECT_ID: address = @0x5;

/// Number of bytes in an object ID
const ID_SIZE: u64 = 20;

Expand Down Expand Up @@ -77,6 +81,12 @@ module Sui::ID {
VersionedID { id: UniqueID { id: ID { bytes } }, version: INITIAL_VERSION }
}

/// Create the `VersionedID` for the singleton SuiSystemState object.
/// This should only be called once from SuiSsytem.
public(friend) fun get_sui_system_state_object_id(): VersionedID {
new_versioned_id(SUI_SYSTEM_STATE_OBJECT_ID)
}

// === reads ===

/// Get the underlying `ID` of `obj`
Expand Down
1 change: 1 addition & 0 deletions sui_programmability/framework/tests/ValidatorSetTests.move
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ module Sui::ValidatorSetTests {
addr,
vector[hint],
vector[hint],
vector[hint],
init_stake,
);
(ctx, validator)
Expand Down
2 changes: 2 additions & 0 deletions sui_programmability/framework/tests/ValidatorTests.move
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module Sui::ValidatorTests {
let init_stake = Coin::into_balance(Coin::mint_for_testing(10, ctx));
let validator = Validator::new(
sender,
x"FF",
b"Validator1",
x"FFFF",
init_stake,
Expand Down Expand Up @@ -45,6 +46,7 @@ module Sui::ValidatorTests {
let init_stake = Coin::into_balance(Coin::mint_for_testing(10, ctx));
let validator = Validator::new(
sender,
x"FF",
b"Validator1",
x"FFFF",
init_stake,
Expand Down

0 comments on commit 219a402

Please sign in to comment.