facebookexperimental / MIRAI

Rust mid-level IR Abstract Interpreter

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Question: Foreign contracts

masapr opened this issue · comments

commented

I'd like to use a dummy implementation for some library function my code is using. As far as I understand this can be done by defining a foreign contract

I'd like to do a dummy implementation for the following:
https://github.com/paritytech/substrate/blob/f7e81b9be4fb3f2906a3768fe74d70c8228ab553/frame/support/src/storage/types/value.rs#L122C10-L122C10

The code, I run the analysis on is here:
https://github.com/scs/MIRAI/blob/Milestone1_Research/substrate-examples/pallet_template/src/lib.rs

Is it correct, that I can simply add a foreign_contracts.rs file next to it? If so, what's the syntax? Is there anything else needed?

This is a tricky and not well documented feature. Looking at the code for it, I think it may need fixing since it still expects a bottom up analysis.

The only place where such a dummy implementation should still be needed is when your library function is not written in Rust. If this is the case, it matters whether or not you control the library code.

Can you expand a bit on your particular situation?

commented

We basically want to do something about point 2, at our findings here. At the link you also find more about, what we're trying to do.

To wrap it up: we want to analyze substrate pallet code (=substrate blockchain logic) with MIRAI. Writing a substrate pallet, means you write your code in Rust and use substrate libraries for the general blockchain stuff. Now, when we analyze the code of a simple substrate pallet, most of the complexity comes from the substrate libraries. But we don't want to analyze the substrate libraries, but only the newly written code. So, I thought the easiest solution would be, to prevent MIRAI from analyzing the library code.

... to be honest, the problems we encountered might also stem from something else. For example, there are also foreign contracts missing in MIRAI for some of the low-level functions used in the substrate libraries. But either way, it's always good to reduce the complexity, right? Also checkout the call_graph we generated for one of the examples

In general, it is going to be easier to just let MIRAI summarize the code you have. But, as you seem to be finding out the hard way, that means that MIRAI has to be beefed up to handle some gnarly substrate code and that is probably beyond the scope of what you are setting out to do.

If you can summarize the substrate code by hand, using just the normal contract language, then you have other options. Easiest would be to annotate the substrate code. Is that at all feasible?

commented

If I know, how to do it with annotations, that would be valuable. If it's feasible I don't know yet. But there's a chance for it. Right now, I don't see, how annotations would prevent MIRAI from analysing the code. E. g. if I put something in storage, I simply want everything ignored, that is happening in there. How would I do this with annotations?

As I understand you, it's also an option to have the library code analyzed beforehand? Is that right? If that's possible, it's probably the cleanest solution and potentially even easier than mocking/summarizing all library functions... how would I implement that? I saw, there's a special setting for analyzing library code. But how can this analysis be used when I run MIRAI on the program using the library?

When MIRAI runs, it sets the configuration switch "mirai". This allows you to put conditionally compiled code into the substrate code that only gets compiled when MIRAI runs. So, you can have something like:

fn gnarly_foo(...) {
  if cfg!("mirai") {
     // annotations that state pre-conditions assumed post conditions. No body needed. MIRAI is relaxed and happy.
  } else {
    // gnarly stuff that stresses out MIRAI
  }
}
commented

Oh thanks. Yes, using compiler flags makes totally sense. I can't believe I didn't see that myself. Then I think there is a way for us to do this.