-
Notifications
You must be signed in to change notification settings - Fork 67
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
Contract Spec #42
Comments
@graydon did some research which looks very useful, details were shared on Discord here. Links from that discussion:
|
I looked through these links, and I think we can do the simplest thing for now, which given our alignment and use of Rust is probably a toml file that looks something like: [contract]
[fns.add32]
args = ["i32", "i32"]
return = "i32"
[fns.add64]
args = ["i64", "i64"]
return = "i64"
[fns.hndmsg]
args = ["obj:binary"]
return = "bool" The above example provides the fields as specified in CAP-47 (@sisuresh). The example assumes that types can be referenced using the |
A simple format like this will be relatively easy to convert into XDR when deploying, but nothing about it necessarily helps us validate a contract function, since a contract function implements itself its conversion logic and so that can only be tested by executing the function, but no general test can confirm that part of a contract is working correctly without potentially executing invalid values that cause the contract to fail for other reasons. |
A large part of the problem of verifying code written by developers is that our contracts currently take the following shape. Since the inputs are all untyped RawVals there's not a lot we can do to validate the types that the functions will use internally. Ideally we end up with code looking like this snippet, where function arguments are typed, it is easy to validate that a function matches a signature, and the conversion is largely hidden from the developer. We had a prototype of supporting this with a procedural macro in #9. However, this doesn't leverage the Rust compiler to actually do that verification, we'd probably have to use To leverage the Rust compiler to validate the shape of the functions implemented we need to use traits to do something like the below. I think this gets us most things we want, except it isn't particularly portable to other languages. But it is compelling that a developer could share a trait and others could implement it, and everybody would be using the compiler they already have on their systems to guarantee compatibility. Of course, this would require us to use a procedural macro, like on the example above, to generate extern fns. |
I think there's a plausible (and possibly kinda forced-on-us) point in the design space where "an interface" is defined as either an XDR manifest or a (bijectively mapped) Rust trait, and we have a proc macro on a unit type (or an impl?) that emits a bunch of global #[no_mangle] pub fns that receive RawVals and call through to to the associated methods on the unit type, with each arg run through into() or try_into(). I'd be willing to see how horrible that is. It's macros which I don't love, but I don't see a lot of other options at this point. |
I agree, that's where I'm landing too. When I prototyped a macro previously in #9 the only benefit was to remove some boilerplate, but now the benefit is greater as it would include the trait being a way developers can share their contract interfaces. I'm going to prototype this and then we can review it and see how bad the tradeoffs are. |
You don't really need the impl there, afaict. You could just implement the contract as the default methods on the trait. Though you'd need some sort of public/private indicator. e.g. #[stellar::contract]
pub trait AddContract {
fn add(_e: Env, a: i64, b: i64) -> i64 {
a + b
}
} For reference, elrond do roughly the same: https://github.com/ElrondNetwork/elrond-wasm-rs/blob/master/contracts/examples/factorial/src/factorial.rs |
Would the typecasting wrapper @graydon suggested need to be a macro? Could it be a sort of runtime within wasm, that loads up the contract code, introspects it, and casts? Edit: Ah, no. because it would need the type signatures which are only available at compile time. |
To test the contract an impl will be required. Developer may as well write it that way. It also makes sharing the trait easier since you can copy and paste it anywhere without the impl. The moment the impl lives in the trait you can't do that. |
@paulbellamy and I discussed this more today and I'm working towards something like the following diagram:
|
@paulbellamy and I also discussed who the stakeholders/users are, and the use cases, and came up with the following relationships and technologies that will possibly touch it: |
Conversations with @paulbellamy and @jonjove have expanded this work in a few things, so I'm going to open issues for each of them and close this issue as I think we have a reasonably good high-level plan now. See the issue description for the list of tasks. |
All the plans live in subissues now, and I'm going to close this parent issue to continue to use the subissues. All issues relating to this will be prefixed with |
This description is updated with the resolution:
The design is here: #42 (comment)
The list of things to do now are here (#42 (comment)):
The text was updated successfully, but these errors were encountered: