Skip to content

Commit

Permalink
Schema generation (#1765)
Browse files Browse the repository at this point in the history
* derive JsonSchema

* fixes

* point to master

* use scale-info 2.6

* remove expand.rs

* changelog entry

* typo

* typo

* add Added section

* remove garbage

* scale-info wildcard version
  • Loading branch information
German authored Apr 27, 2023
1 parent 4ad0b7e commit ab825a4
Show file tree
Hide file tree
Showing 50 changed files with 92 additions and 72 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- Schema generation - [#1765](https://github.com/paritytech/ink/pull/1765)

## Version 4.2.0

### Added
Expand Down
2 changes: 1 addition & 1 deletion crates/e2e/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ sp-weights = "19.0.0"

[dev-dependencies]
# Required for the doctest of `MessageBuilder::call`
scale-info = { version = "2.5", default-features = false, features = ["derive"] }
scale-info = { version = "2.6", default-features = false, features = ["derive"] }

[features]
default = ["std"]
Expand Down
2 changes: 1 addition & 1 deletion crates/env/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ secp256k1 = { version = "0.27.0", features = ["recovery", "global-context"], opt
# Never use this crate outside the off-chain environment!
scale-decode = { version = "0.5.0", default-features = false, optional = true }
scale-encode = { version = "0.1.0", default-features = false, optional = true }
scale-info = { version = "2.5", default-features = false, features = ["derive"], optional = true }
scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true }

[dev-dependencies]
ink = { path = "../ink" }
Expand Down
2 changes: 1 addition & 1 deletion crates/ink/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ ink_metadata = { path = "../metadata", default-features = false }

trybuild = { version = "1.0.60", features = ["diff"] }
# Required for the doctest of `env_access::EnvAccess::instantiate_contract`
scale-info = { version = "2.5", default-features = false, features = ["derive"] }
scale-info = { version = "2.6", default-features = false, features = ["derive"] }

[features]
default = ["std"]
Expand Down
2 changes: 1 addition & 1 deletion crates/ink/macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ ink = { path = ".." }
ink_metadata = { path = "../../metadata" }
ink_prelude = { path = "../../prelude" }
ink_storage = { path = "../../storage" }
scale-info = { version = "2.5", default-features = false, features = ["derive"] }
scale-info = { version = "2.6", default-features = false, features = ["derive"] }

[lib]
name = "ink_macro"
Expand Down
3 changes: 2 additions & 1 deletion crates/metadata/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ ink_primitives = { version = "4.2.0", path = "../primitives/", default-features
serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] }
impl-serde = "0.4.0"
derive_more = { version = "0.99", default-features = false, features = ["from"] }
scale-info = { version = "2.5", default-features = false, features = ["derive", "serde", "decode"] }
scale-info = { version = "2.6", default-features = false, features = ["derive", "serde", "decode", "schema"] }
schemars = "0.8"

[dev-dependencies]
pretty_assertions = "1"
Expand Down
38 changes: 26 additions & 12 deletions crates/metadata/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,17 @@ use scale_info::{
Registry,
TypeInfo,
};
use schemars::JsonSchema;
use serde::{
de::DeserializeOwned,
Deserialize,
Serialize,
};

/// Represents the static storage layout of an ink! smart contract.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, From, Serialize, Deserialize)]
#[derive(
Debug, PartialEq, Eq, PartialOrd, Ord, From, Serialize, Deserialize, JsonSchema,
)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
Expand All @@ -74,7 +77,7 @@ pub enum Layout<F: Form = MetaForm> {
}

/// A pointer into some storage region.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, From)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, From, JsonSchema)]
pub struct LayoutKey {
key: Key,
}
Expand Down Expand Up @@ -121,13 +124,16 @@ impl LayoutKey {
}

/// Sub-tree root.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, From, Serialize, Deserialize)]
#[derive(
Debug, PartialEq, Eq, PartialOrd, Ord, From, Serialize, Deserialize, JsonSchema,
)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
))]
pub struct RootLayout<F: Form = MetaForm> {
/// The root key of the sub-tree.
#[schemars(with = "String")]
root_key: LayoutKey,
/// The storage layout of the unbounded layout elements.
layout: Box<Layout<F>>,
Expand Down Expand Up @@ -171,13 +177,16 @@ where
}

/// A SCALE encoded cell.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, From, Serialize, Deserialize)]
#[derive(
Debug, PartialEq, Eq, PartialOrd, Ord, From, Serialize, Deserialize, JsonSchema,
)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
))]
pub struct LeafLayout<F: Form = MetaForm> {
/// The offset key into the storage.
#[schemars(with = "String")]
key: LayoutKey,
/// The type of the encoded entity.
ty: <F as Form>::Type,
Expand Down Expand Up @@ -256,13 +265,14 @@ where
/// A hashing layout potentially hitting all cells of the storage.
///
/// Every hashing layout has an offset and a strategy to compute its keys.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
))]
pub struct HashLayout<F: Form = MetaForm> {
/// The key offset used by the strategy.
#[schemars(with = "String")]
offset: LayoutKey,
/// The hashing strategy to layout the underlying elements.
strategy: HashingStrategy,
Expand Down Expand Up @@ -322,7 +332,7 @@ where
/// The offset key is used as another postfix for the computation.
/// So the actual formula is: `hasher(prefix + encoded(key) + offset + postfix)`
/// Where `+` in this contexts means append of the byte slices.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema)]
pub struct HashingStrategy {
/// One of the supported crypto hashers.
hasher: CryptoHasher,
Expand Down Expand Up @@ -367,7 +377,7 @@ impl HashingStrategy {
}

/// One of the supported crypto hashers.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema)]
pub enum CryptoHasher {
/// The BLAKE-2 crypto hasher with an output of 256 bits.
Blake2x256,
Expand All @@ -378,7 +388,7 @@ pub enum CryptoHasher {
}

/// A layout for an array of associated cells with the same encoding.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
Expand All @@ -388,6 +398,7 @@ pub struct ArrayLayout<F: Form = MetaForm> {
/// The offset key of the array layout.
///
/// This is the same key as the element at index 0 of the array layout.
#[schemars(with = "String")]
offset: LayoutKey,
/// The number of elements in the array layout.
len: u32,
Expand Down Expand Up @@ -446,7 +457,7 @@ impl IntoPortable for ArrayLayout {
}

/// A struct layout with consecutive fields of different layout.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
Expand Down Expand Up @@ -500,7 +511,7 @@ impl IntoPortable for StructLayout {
}

/// The layout for a particular field of a struct layout.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
Expand Down Expand Up @@ -557,7 +568,9 @@ impl IntoPortable for FieldLayout {
}

/// The discriminant of an enum variant.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[derive(
Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema,
)]
pub struct Discriminant(usize);

impl From<usize> for Discriminant {
Expand All @@ -574,7 +587,7 @@ impl Discriminant {
}

/// An enum storage layout.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
Expand All @@ -584,6 +597,7 @@ pub struct EnumLayout<F: Form = MetaForm> {
/// The name of the Enum.
name: F::String,
/// The key where the discriminant is stored to dispatch the variants.
#[schemars(with = "String")]
dispatch_key: LayoutKey,
/// The variants of the enum.
variants: BTreeMap<Discriminant, StructLayout<F>>,
Expand Down
5 changes: 3 additions & 2 deletions crates/metadata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ use scale_info::{
PortableRegistry,
Registry,
};
use schemars::JsonSchema;
use serde::{
Deserialize,
Serialize,
Expand All @@ -76,7 +77,7 @@ use serde::{
/// Versions other than the `Default` are considered deprecated. If you want to
/// deserialize legacy metadata versions you will need to use an old version of
/// this crate.
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, JsonSchema)]
pub enum MetadataVersion {
#[serde(rename = "4")]
V4,
Expand All @@ -89,7 +90,7 @@ impl Default for MetadataVersion {
}

/// An entire ink! project for metadata file generation purposes.
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct InkProject {
version: MetadataVersion,
#[serde(flatten)]
Expand Down
23 changes: 12 additions & 11 deletions crates/metadata/src/specs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@ use scale_info::{
Registry,
TypeInfo,
};
use schemars::JsonSchema;
use serde::{
de::DeserializeOwned,
Deserialize,
Serialize,
};

/// Describes a contract.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
Expand Down Expand Up @@ -289,7 +290,7 @@ where
}

/// Describes a constructor of a contract.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned",
Expand Down Expand Up @@ -529,7 +530,7 @@ where
}

/// Describes a contract message.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
Expand Down Expand Up @@ -837,7 +838,7 @@ impl IntoPortable for MessageSpec {
}

/// Describes an event definition.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
Expand Down Expand Up @@ -949,8 +950,8 @@ where
}

/// The 4 byte selector to identify constructors and messages
#[derive(Debug, Default, PartialEq, Eq, derive_more::From)]
pub struct Selector([u8; 4]);
#[derive(Debug, Default, PartialEq, Eq, derive_more::From, JsonSchema)]
pub struct Selector(#[schemars(with = "String")] [u8; 4]);

impl serde::Serialize for Selector {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
Expand Down Expand Up @@ -1023,7 +1024,7 @@ pub type DisplayName<F> = scale_info::Path<F>;
/// `pred`s display name is `Predicate` and the display name of
/// the return type is simply `bool`. Note that `Predicate` could
/// simply be a type alias to `fn(i32, i32) -> Ordering`.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
Expand Down Expand Up @@ -1145,7 +1146,7 @@ where
}

/// Describes a pair of parameter label and type.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
Expand Down Expand Up @@ -1264,7 +1265,7 @@ where
}

/// Describes the contract message return type.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(transparent)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
Expand Down Expand Up @@ -1316,7 +1317,7 @@ where
}

/// Describes a pair of parameter label and type.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
Expand Down Expand Up @@ -1392,7 +1393,7 @@ where
}

/// Describes a contract environment.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(bound(
serialize = "F::Type: Serialize, F::String: Serialize",
deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
Expand Down
2 changes: 1 addition & 1 deletion crates/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ ink_prelude = { version = "4.2.0", path = "../prelude/", default-features = fals
scale = { package = "parity-scale-codec", version = "3.4", default-features = false, features = ["derive"] }
scale-decode = { version = "0.5.0", default-features = false, features = ["derive"], optional = true }
scale-encode = { version = "0.1.0", default-features = false, features = ["derive"], optional = true }
scale-info = { version = "2.5", default-features = false, features = ["derive"], optional = true }
scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true }
xxhash-rust = { version = "0.8", features = ["const_xxh32"] }

[features]
Expand Down
2 changes: 1 addition & 1 deletion crates/storage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ ink_prelude = { version = "4.2.0", path = "../prelude/", default-features = fals

scale = { package = "parity-scale-codec", version = "3.4", default-features = false, features = ["derive"] }
derive_more = { version = "0.99", default-features = false, features = ["from", "display"] }
scale-info = { version = "2.5", default-features = false, features = ["derive"], optional = true }
scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true }
cfg-if = "1.0"
array-init = { version = "2.0", default-features = false }

Expand Down
2 changes: 1 addition & 1 deletion crates/storage/traits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ ink_metadata = { version = "4.2.0", path = "../../metadata", default-features =
ink_primitives = { version = "4.2.0", path = "../../primitives", default-features = false }
ink_prelude = { version = "4.2.0", path = "../../prelude", default-features = false }
scale = { package = "parity-scale-codec", version = "3.4", default-features = false, features = ["derive"] }
scale-info = { version = "2.5", default-features = false, features = ["derive"], optional = true }
scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true }

[dev-dependencies]
paste = "1.0"
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/basic-contract-caller/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ publish = false
ink = { path = "../../crates/ink", default-features = false }

scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
scale-info = { version = "2.5", default-features = false, features = ["derive"], optional = true }
scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true }

# Note: We **need** to specify the `ink-as-dependency` feature.
#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ publish = false
ink = { path = "../../../crates/ink", default-features = false }

scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
scale-info = { version = "2.5", default-features = false, features = ["derive"], optional = true }
scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true }

[dev-dependencies]
ink_e2e = { path = "../../../crates/e2e" }
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/call-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ publish = false
ink = { path = "../../crates/ink", default-features = false, features = ["call-runtime"] }

scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
scale-info = { version = "2.5", default-features = false, features = ["derive"], optional = true }
scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true }

# Substrate
#
Expand Down
Loading

0 comments on commit ab825a4

Please sign in to comment.