Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New metadata format #296

Merged
merged 31 commits into from Jun 13, 2020
Merged

New metadata format #296

merged 31 commits into from Jun 13, 2020

Conversation

ascjones
Copy link
Collaborator

@ascjones ascjones commented Dec 10, 2019

Closes #294.

  • Use externally tagged enums e.g. instead of "range.offset" use "range": { "offset" }
  • Convert field names to camelCase instead of snake_case
  • Selector bytes encoded as hex string e.g. instead of "[\"0x07\",\"0x5B\",\"0xCD\",\"0x15\"]" use "0x075bcd15"
  • Convert from type-metadata to https://github.com/paritytech/scale-info

The new type registry serialization depends on paritytech/scale-info#3, so only once that is merged will you get the full new format.

e.g. Incrementer:

{
  "registry": {
    "strings": [
      "Storage",
      "flipper",
      "__ink_private",
      "__ink_storage",
      "value",
      "Value",
      "ink_core",
      "storage",
      "cell",
      "SyncCell",
      "sync_cell",
      "Key",
      "ink_primitives",
      "key",
      "new",
      "init_value",
      "bool",
      "default",
      "flip",
      "get"
    ],
    "types": [
      {
        "composite": {
          "name": 1,
          "namespace": [
            2,
            2,
            3,
            4
          ],
          "fields": [
            {
              "name": 5,
              "type": 2
            }
          ]
        }
      },
      {
        "composite": {
          "name": 6,
          "namespace": [
            7,
            8,
            5
          ],
          "params": [
            3
          ],
          "fields": [
            {
              "name": 9,
              "type": 4
            }
          ]
        }
      },
      {
        "primitive": "bool"
      },
      {
        "composite": {
          "name": 10,
          "namespace": [
            7,
            8,
            9,
            11
          ],
          "fields": [
            {
              "name": 9,
              "type": 5
            }
          ]
        }
      },
      {
        "composite": {
          "name": 12,
          "namespace": [
            13,
            14
          ],
          "fields": [
            {
              "type": 6
            }
          ]
        }
      },
      {
        "array": {
          "len": 32,
          "type": 7
        }
      },
      {
        "primitive": "u8"
      }
    ]
  },
  "storage": {
    "struct": {
      "type": 1,
      "fields": [
        {
          "name": 5,
          "layout": {
            "struct": {
              "type": 2,
              "fields": [
                {
                  "name": 9,
                  "layout": {
                    "range": {
                      "offset": "0x0000000000000000000000000000000000000000000000000000000000000000",
                      "len": 1,
                      "elemType": 3
                    }
                  }
                }
              ]
            }
          }
        }
      ]
    }
  },
  "contract": {
    "name": 2,
    "constructors": [
      {
        "name": 15,
        "selector": "0x5ebd88d6",
        "args": [
          {
            "name": 16,
            "type": {
              "id": 3,
              "displayName": [
                17
              ]
            }
          }
        ],
        "docs": []
      },
      {
        "name": 18,
        "selector": "0x0222ff18",
        "args": [],
        "docs": []
      }
    ],
    "messages": [
      {
        "name": 19,
        "selector": "0x8c97db39",
        "mutates": true,
        "args": [],
        "returnType": null,
        "docs": []
      },
      {
        "name": 20,
        "selector": "0x25444afe",
        "mutates": false,
        "args": [],
        "returnType": {
          "id": 3,
          "displayName": [
            17
          ]
        },
        "docs": []
      }
    ],
    "events": [],
    "docs": []
  }
}

@codecov-io
Copy link

codecov-io commented Dec 10, 2019

Codecov Report

❗ No coverage uploaded for pull request base (master@e020402). Click here to learn what that means.
The diff coverage is 98.86%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master     #296   +/-   ##
=========================================
  Coverage          ?   72.45%           
=========================================
  Files             ?       76           
  Lines             ?     6604           
  Branches          ?        0           
=========================================
  Hits              ?     4785           
  Misses            ?     1819           
  Partials          ?        0
Impacted Files Coverage Δ
abi/src/tests.rs 100% <100%> (ø)
abi/src/layout.rs 50.72% <100%> (ø)
abi/src/lib.rs 63.63% <100%> (ø)
abi/src/specs.rs 70% <80%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e020402...49e5d32. Read the comment docs.

@Robbepop
Copy link
Collaborator

Superseedes #264

Robbepop
Robbepop previously approved these changes Dec 10, 2019
Copy link
Collaborator

@Robbepop Robbepop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

I very much like that you actually added a wholesome test.
Let's merge this as soon as Polkadot JS gave their acknowledgement that their JSON parser can trivially parse the output of this PR.

@jacogr
Copy link

jacogr commented Dec 11, 2019

Is it possible to sneak in a version number into the InkProject struct? That would be beneficial going forward as well.

@Robbepop
Copy link
Collaborator

Robbepop commented Dec 11, 2019

Is it possible to sneak in a version number into the InkProject struct? That would be beneficial going forward as well.

I was talking to Sean Young who implements the Solang Solidity to Wasm compiler and we want to share our metadata format for the contracts.
So for this purpose I think it would also be beneficial to include some kind of "language" property into the InkProject struct that is simply ink for ink! contracts for a start.

Also we though that some other metadata would be nice to have.
E.g. some hashes over the code to properly infer if the supplied code matches the metadata, the author of the contract to make it possible to contact maintainers, the used Rust (or other compiler) version to have "more deterministic" way to rebuild the contract etc.

What do you think?

cc @seanyoung

@jacogr
Copy link

jacogr commented Dec 11, 2019

@Robbepop It makes sense, the additional metadata is quite easy to add as a sub-structure, and is certainly very beneficial as we expand.

@ascjones
Copy link
Collaborator Author

Should this versioning/language field be done as a separate PR?

@Robbepop
Copy link
Collaborator

Should this versioning/language field be done as a separate PR?

Yes, also can you write an issue for that so we can track and discuss there what needs to be added exactly?

@jacogr
Copy link

jacogr commented Dec 12, 2019

Going through, think this is not correctly named/consistent -

"constructors": [
      {
        "name": 36,
        "selector": "0x5ebd88d6",
        "args": [
          {
            "name": 37,
            "type": {
              "ty": 4,
              "displayName": [
                38
              ]
            }
          }
        ],
        "docs": []
      },

ty above

@ascjones
Copy link
Collaborator Author

So should ty be type then? So it would be type.type

@Robbepop
Copy link
Collaborator

So should ty be type then? So it would be type.type

Well ty is an ID, so just call it id.

@ascjones
Copy link
Collaborator Author

Should this versioning/language field be done as a separate PR?

Yes, also can you write an issue for that so we can track and discuss there what needs to be added exactly?

#299

@ascjones
Copy link
Collaborator Author

Let's merge this as soon as Polkadot JS gave their acknowledgement that their JSON parser can trivially parse the output of this PR.

@jacogr are we good to go on your end?

# Conflicts:
#	.gitlab-ci.yml
#	abi/Cargo.toml
#	core/Cargo.toml
#	examples/delegator/Cargo.toml
#	examples/delegator/accumulator/Cargo.toml
#	examples/delegator/adder/Cargo.toml
#	examples/delegator/subber/Cargo.toml
#	examples/dns/Cargo.toml
#	examples/erc20/Cargo.toml
#	examples/erc721/Cargo.toml
#	examples/flipper/Cargo.toml
#	examples/incrementer/Cargo.toml
#	examples/multisig_plain/Cargo.toml
#	examples/runtime-storage/Cargo.toml
#	lang/macro/Cargo.toml
#	primitives/Cargo.toml
@ascjones ascjones changed the title Standardize metadata format New metadata format Mar 23, 2020
@ascjones
Copy link
Collaborator Author

bors try

bors bot added a commit that referenced this pull request Mar 24, 2020
@bors
Copy link
Contributor

bors bot commented Mar 24, 2020

try

Build failed

@ascjones
Copy link
Collaborator Author

ascjones commented Mar 26, 2020

Now updated to use scale-info with new format. e.g. Incrementer:

{
  "registry": {
    "strings": [
      "Storage",
      "incrementer",
      "__ink_private",
      "__ink_storage",
      "value",
      "Value",
      "ink_core",
      "storage",
      "cell",
      "SyncCell",
      "sync_cell",
      "Key",
      "ink_primitives",
      "key",
      "new",
      "init_value",
      "i32",
      "default",
      "inc",
      "by",
      "get"
    ],
    "types": [
      {
        "composite": {
          "name": 1,
          "namespace": [
            2,
            2,
            3,
            4
          ],
          "fields": [
            {
              "name": 5,
              "type": 2
            }
          ]
        }
      },
      {
        "composite": {
          "name": 6,
          "namespace": [
            7,
            8,
            5
          ],
          "params": [
            3
          ],
          "fields": [
            {
              "name": 9,
              "type": 4
            }
          ]
        }
      },
      {
        "primitive": "i32"
      },
      {
        "composite": {
          "name": 10,
          "namespace": [
            7,
            8,
            9,
            11
          ],
          "fields": [
            {
              "name": 9,
              "type": 5
            }
          ]
        }
      },
      {
        "composite": {
          "name": 12,
          "namespace": [
            13,
            14
          ],
          "fields": [
            {
              "type": 6
            }
          ]
        }
      },
      {
        "array": {
          "len": 32,
          "type": 7
        }
      },
      {
        "primitive": "u8"
      }
    ]
  },
  "storage": {
    "struct": {
      "type": 1,
      "fields": [
        {
          "name": 5,
          "layout": {
            "struct": {
              "type": 2,
              "fields": [
                {
                  "name": 9,
                  "layout": {
                    "range": {
                      "offset": "0x0000000000000000000000000000000000000000000000000000000000000000",
                      "len": 1,
                      "elemType": 3
                    }
                  }
                }
              ]
            }
          }
        }
      ]
    }
  },
  "contract": {
    "name": 2,
    "constructors": [
      {
        "name": 15,
        "selector": "0x5ebd88d6",
        "args": [
          {
            "name": 16,
            "type": {
              "id": 3,
              "displayName": [
                17
              ]
            }
          }
        ],
        "docs": []
      },
      {
        "name": 18,
        "selector": "0x0222ff18",
        "args": [],
        "docs": []
      }
    ],
    "messages": [
      {
        "name": 19,
        "selector": "0xe7d0590f",
        "mutates": true,
        "args": [
          {
            "name": 20,
            "type": {
              "id": 3,
              "displayName": [
                17
              ]
            }
          }
        ],
        "returnType": null,
        "docs": []
      },
      {
        "name": 21,
        "selector": "0x25444afe",
        "mutates": false,
        "args": [],
        "returnType": {
          "id": 3,
          "displayName": [
            17
          ]
        },
        "docs": []
      }
    ],
    "events": [],
    "docs": []
  }
}

Copy link
Collaborator

@Robbepop Robbepop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but we should merge this after type-info PR is merged into master and replace the explicit branches here.

abi/src/layout.rs Show resolved Hide resolved
@@ -83,3 +90,15 @@ impl InkProject {
}
}
}

fn hex_encode<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use some documentation with a simple example.

# Conflicts:
#	primitives/src/key.rs
@codecov-commenter
Copy link

codecov-commenter commented Jun 11, 2020

Codecov Report

Merging #296 into master will increase coverage by 1.28%.
The diff coverage is 59.09%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #296      +/-   ##
==========================================
+ Coverage   86.83%   88.11%   +1.28%     
==========================================
  Files         135      136       +1     
  Lines        5877     5924      +47     
==========================================
+ Hits         5103     5220     +117     
+ Misses        774      704      -70     
Impacted Files Coverage Δ
abi/derive/src/has_layout.rs 74.19% <ø> (ø)
abi/derive/src/impl_wrapper.rs 100.00% <ø> (ø)
core/src/env/types.rs 23.52% <ø> (ø)
core/src/storage/alloc/bump_alloc.rs 88.88% <ø> (ø)
core/src/storage/alloc/dyn_alloc.rs 83.82% <ø> (ø)
core/src/storage/cell/sync_cell.rs 86.72% <0.00%> (-1.57%) ⬇️
core/src/storage/chunk/sync_chunk/chunk.rs 76.74% <0.00%> (-3.75%) ⬇️
...orage/collections/binary_heap/duplex_sync_chunk.rs 97.87% <ø> (ø)
core/src/storage/collections/binary_heap/impls.rs 97.47% <ø> (ø)
core/src/storage/collections/bitvec/block.rs 100.00% <ø> (ø)
... and 19 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 13eb43e...a8f3ad6. Read the comment docs.

examples/flipper/.ink/abi_gen/metadata.json Outdated Show resolved Hide resolved
examples/flipper/something/.rustc_info.json Outdated Show resolved Hide resolved
@ascjones
Copy link
Collaborator Author

I know the current storage module is being replaced, but I have fixed the compilation errors anyway

@ascjones
Copy link
Collaborator Author

Latest incrementer metadata.json:

{
  "registry": {
    "strings": [
      "incrementer",
      "__ink_private",
      "__ink_storage",
      "Storage",
      "value",
      "ink_core",
      "storage",
      "Value",
      "cell",
      "sync_cell",
      "SyncCell",
      "ink_primitives",
      "key",
      "Key",
      "new",
      "init_value",
      "i32",
      "default",
      "inc",
      "by",
      "get"
    ],
    "types": [
      {
        "path": [
          1,
          1,
          2,
          3,
          4
        ],
        "composite": {
          "fields": [
            {
              "name": 5,
              "type": 2
            }
          ]
        }
      },
      {
        "path": [
          6,
          7,
          5,
          8
        ],
        "params": [
          3
        ],
        "composite": {
          "fields": [
            {
              "name": 9,
              "type": 4
            }
          ]
        }
      },
      {
        "primitive": "i32"
      },
      {
        "path": [
          6,
          7,
          9,
          10,
          11
        ],
        "composite": {
          "fields": [
            {
              "name": 9,
              "type": 5
            }
          ]
        }
      },
      {
        "path": [
          12,
          13,
          14
        ],
        "composite": {
          "fields": [
            {
              "type": 6
            }
          ]
        }
      },
      {
        "array": {
          "len": 32,
          "type": 7
        }
      },
      {
        "primitive": "u8"
      }
    ]
  },
  "storage": {
    "struct": {
      "type": 1,
      "fields": [
        {
          "name": 5,
          "layout": {
            "struct": {
              "type": 2,
              "fields": [
                {
                  "name": 9,
                  "layout": {
                    "range": {
                      "offset": "0x0000000000000000000000000000000000000000000000000000000000000000",
                      "len": 1,
                      "elemType": 3
                    }
                  }
                }
              ]
            }
          }
        }
      ]
    }
  },
  "contract": {
    "name": 1,
    "constructors": [
      {
        "name": 15,
        "selector": "0x5ebd88d6",
        "args": [
          {
            "name": 16,
            "type": {
              "id": 3,
              "displayName": [
                17
              ]
            }
          }
        ],
        "docs": []
      },
      {
        "name": 18,
        "selector": "0x0222ff18",
        "args": [],
        "docs": []
      }
    ],
    "messages": [
      {
        "name": 19,
        "selector": "0xe7d0590f",
        "mutates": true,
        "args": [
          {
            "name": 20,
            "type": {
              "id": 3,
              "displayName": [
                17
              ]
            }
          }
        ],
        "returnType": null,
        "docs": []
      },
      {
        "name": 21,
        "selector": "0x25444afe",
        "mutates": false,
        "args": [],
        "returnType": {
          "id": 3,
          "displayName": [
            17
          ]
        },
        "docs": []
      }
    ],
    "events": [],
    "docs": []
  }
}

Copy link
Collaborator

@Robbepop Robbepop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment on lines -840 to -864
#[cfg(test)]
mod tests {
use super::*;

#[test]
fn construct_selector_must_serialize_to_hex() {
// given
let name = "foo";
let cs: ConstructorSpec<MetaForm> = ConstructorSpec {
name,
selector: 123_456_789u32.to_be_bytes(),
args: Vec::new(),
docs: Vec::new(),
};
let mut registry = Registry::new();

// when
let json = serde_json::to_string(&cs.into_compact(&mut registry)).unwrap();

// then
assert_eq!(
json,
r#"{"name":1,"selector":"[\"0x07\",\"0x5B\",\"0xCD\",\"0x15\"]","args":[],"docs":[]}"#
);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this test moved or removed?

@Robbepop Robbepop merged commit 5a7b7e5 into master Jun 13, 2020
@Robbepop Robbepop deleted the aj-metadata branch June 13, 2020 09:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Contract metadata format
5 participants