Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[sui move] generate layouts for Move structs
Add build option to SuiCompiledPackage that generate a `serde-reflection` `Registry` containing the layout of relevant structs in the package. For now, we define "relevant" as the structs declared by each module in the package, plus the struct types passed to entry functions of each module (either directly or by reference). A `Registry` lets you do a bunch of useful things: - Write logic in our BCS Typescript SDK that consumes a `Registry` YAML file and automatically calls `bcs.registerStructType` on every entry in the registry. This will hopefully make writing Sui web apps much faster--if you've written Move types already, you get the TS type definitions + BCS serializers and deserializers for free. - Use `serde-generate` https://github.com/zefchain/serde-reflection/tree/main/serde-generate to generate type definitions from a `Registry` in a variety of languages (e.g. Python, Go, Rust, Java, Swift, C++). This makes it much easier to write an SDK that talks to an on-chain Move package in these langs because you can generate all the boilerplate wrapper types. - Autogenerate a `Registry` for your types that should not change, serialize the result to a YAML file, check it in, and then use this to detect breaking changes to those types. We do this for our key Rust types used in txes etc. Check out https://github.com/MystenLabs/sui/blob/main/crates/sui-core/tests/README.md--https://github.com/MystenLabs/sui/blob/main/crates/sui-core/tests/staged/sui.yaml is a serialized `Registry` autogenerated in the manner described above. Here's an example of what the `Registry` for the `games` package looks like: ``` --- "0000000000000000000000000000000000000000::hero::Boar": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - hp: U64 - strength: U64 - game_id: TYPENAME: "0000000000000000000000000000000000000002::object::ID" "0000000000000000000000000000000000000000::hero::BoarSlainEvent": STRUCT: - slayer_address: TYPENAME: AccountAddress - hero: TYPENAME: "0000000000000000000000000000000000000002::object::ID" - boar: TYPENAME: "0000000000000000000000000000000000000002::object::ID" - game_id: TYPENAME: "0000000000000000000000000000000000000002::object::ID" "0000000000000000000000000000000000000000::hero::GameAdmin": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - boars_created: U64 - potions_created: U64 - game_id: TYPENAME: "0000000000000000000000000000000000000002::object::ID" "0000000000000000000000000000000000000000::hero::GameInfo": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - admin: TYPENAME: AccountAddress "0000000000000000000000000000000000000000::hero::Hero": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - hp: U64 - experience: U64 - sword: TYPENAME: "0000000000000000000000000000000000000001::option::Option<0000000000000000000000000000000000000000::hero::Sword>" - game_id: TYPENAME: "0000000000000000000000000000000000000002::object::ID" "0000000000000000000000000000000000000000::hero::Potion": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - potency: U64 - game_id: TYPENAME: "0000000000000000000000000000000000000002::object::ID" "0000000000000000000000000000000000000000::hero::Sword": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - magic: U64 - strength: U64 - game_id: TYPENAME: "0000000000000000000000000000000000000002::object::ID" "0000000000000000000000000000000000000000::rock_paper_scissors::Game": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - prize: TYPENAME: "0000000000000000000000000000000000000000::rock_paper_scissors::ThePrize" - player_one: TYPENAME: AccountAddress - player_two: TYPENAME: AccountAddress - hash_one: BYTES - hash_two: BYTES - gesture_one: U8 - gesture_two: U8 "0000000000000000000000000000000000000000::rock_paper_scissors::PlayerTurn": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - hash: BYTES - player: TYPENAME: AccountAddress "0000000000000000000000000000000000000000::rock_paper_scissors::Secret": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - salt: BYTES - player: TYPENAME: AccountAddress "0000000000000000000000000000000000000000::rock_paper_scissors::ThePrize": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" "0000000000000000000000000000000000000000::sea_hero::RUM": STRUCT: - dummy_field: BOOL "0000000000000000000000000000000000000000::sea_hero::SeaHeroAdmin": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - supply: TYPENAME: "0000000000000000000000000000000000000002::balance::Supply<0000000000000000000000000000000000000000::sea_hero::RUM>" - monsters_created: U64 - token_supply_max: U64 - monster_max: U64 "0000000000000000000000000000000000000000::sea_hero::SeaMonster": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - reward: TYPENAME: "0000000000000000000000000000000000000002::balance::Balance<0000000000000000000000000000000000000000::sea_hero::RUM>" "0000000000000000000000000000000000000000::sea_hero_helper::HelpMeSlayThisMonster": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - monster: TYPENAME: "0000000000000000000000000000000000000000::sea_hero::SeaMonster" - monster_owner: TYPENAME: AccountAddress - helper_reward: U64 "0000000000000000000000000000000000000000::shared_tic_tac_toe::GameEndEvent": STRUCT: - game_id: TYPENAME: "0000000000000000000000000000000000000002::object::ID" "0000000000000000000000000000000000000000::shared_tic_tac_toe::TicTacToe": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - gameboard: SEQ: BYTES - cur_turn: U8 - game_status: U8 - x_address: TYPENAME: AccountAddress - o_address: TYPENAME: AccountAddress "0000000000000000000000000000000000000000::shared_tic_tac_toe::Trophy": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" "0000000000000000000000000000000000000000::tic_tac_toe::GameEndEvent": STRUCT: - game_id: TYPENAME: "0000000000000000000000000000000000000002::object::ID" "0000000000000000000000000000000000000000::tic_tac_toe::Mark": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - player: TYPENAME: AccountAddress - row: U64 - col: U64 "0000000000000000000000000000000000000000::tic_tac_toe::MarkMintCap": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - game_id: TYPENAME: "0000000000000000000000000000000000000002::object::ID" - remaining_supply: U8 "0000000000000000000000000000000000000000::tic_tac_toe::MarkSentEvent": STRUCT: - game_id: TYPENAME: "0000000000000000000000000000000000000002::object::ID" - mark_id: TYPENAME: "0000000000000000000000000000000000000002::object::ID" "0000000000000000000000000000000000000000::tic_tac_toe::TicTacToe": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - gameboard: SEQ: SEQ: TYPENAME: "0000000000000000000000000000000000000001::option::Option<0000000000000000000000000000000000000000::tic_tac_toe::Mark>" - cur_turn: U8 - game_status: U8 - x_address: TYPENAME: AccountAddress - o_address: TYPENAME: AccountAddress "0000000000000000000000000000000000000000::tic_tac_toe::Trophy": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" "0000000000000000000000000000000000000001::option::Option<0000000000000000000000000000000000000000::hero::Sword>": STRUCT: - vec: SEQ: TYPENAME: "0000000000000000000000000000000000000000::hero::Sword" "0000000000000000000000000000000000000001::option::Option<0000000000000000000000000000000000000000::tic_tac_toe::Mark>": STRUCT: - vec: SEQ: TYPENAME: "0000000000000000000000000000000000000000::tic_tac_toe::Mark" "0000000000000000000000000000000000000002::balance::Balance<0000000000000000000000000000000000000000::sea_hero::RUM>": STRUCT: - value: U64 "0000000000000000000000000000000000000002::balance::Balance<0000000000000000000000000000000000000002::sui::SUI>": STRUCT: - value: U64 "0000000000000000000000000000000000000002::balance::Supply<0000000000000000000000000000000000000000::sea_hero::RUM>": STRUCT: - value: U64 "0000000000000000000000000000000000000002::coin::Coin<0000000000000000000000000000000000000002::sui::SUI>": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::UID" - balance: TYPENAME: "0000000000000000000000000000000000000002::balance::Balance<0000000000000000000000000000000000000002::sui::SUI>" "0000000000000000000000000000000000000002::object::ID": STRUCT: - bytes: TYPENAME: AccountAddress "0000000000000000000000000000000000000002::object::UID": STRUCT: - id: TYPENAME: "0000000000000000000000000000000000000002::object::ID" "0000000000000000000000000000000000000002::sui::SUI": STRUCT: - dummy_field: BOOL "0000000000000000000000000000000000000002::tx_context::TxContext": STRUCT: - signer: TYPENAME: Signer - tx_hash: BYTES - epoch: U64 - ids_created: U64 AccountAddress: NEWTYPESTRUCT: TUPLEARRAY: CONTENT: U8 SIZE: 20 Signer: NEWTYPESTRUCT: TUPLEARRAY: CONTENT: U8 SIZE: 20 ``` This contains all declared structs, all structs passed as arguments to `entry` functions, and all of the types they (transitively) depend on. Note: there are a number of fixes we need to make to `SerdeLayoutGenerator` to really get this working. The biggest problem now is that the generator will not create layout files for open types (i.e., struct declarations with unbound type parameters). Note: this PR also upgrades the Move version to pull in a fix to `SerdeLayoutGenerator` that I needed. This required a few updates to the gas logic--please take a look @oxade.
- Loading branch information