rchain / rchain

Blockchain (smart contract) platform using CBC-Casper proof of stake + Rholang for concurrent execution.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Why don't we still have local contracts in Rholang?

hilltracer opened this issue · comments

This question has been tormenting me since I started optimizing the reducer.
Sending data to HotStore is the main performance issue in Rholang data processing at the moment. Proof of this can be found here:
#3700
#3743

When sending data to HotStore, need to spend time for:

  • Serializing;
  • Hashing;
  • Sorting;
  • Refunding (We must refund the full cost for matched com events);
  • Also we need spend time and disc space to save in BlockStore and sending to the validators.

Illustrative example 1

Bad programmer

Suppose I want to write hello to Stas, Tomislav and Anton:

new сhat in {
      сhat!("Hello, Stas!!!")
    | сhat!("Hello, Tomislav!!!") 
    | сhat!("Hello, Anton!!!") 
}
  • Ok, I sent data to the HotStor only 3 times.
  • 3 entries will appear in the event log.
  • As a result of processing this code, only the data I need will appear in the storage.

Good programmer

But if I were a good programmer, I would write helper contract sayHello:

new sayHello, сhat in {
      contract sayHello(@name) = {сhat!("Hello, " ++ name ++ "!!!")}
    | sayHello!("Stas") | sayHello!("Tomislav") | sayHello!("Anton")
}
  • This code does the same but takes twice as long to execute. Because the system is processing helper contract sayHello similar as main сhat.
  • 6 operations will be added to the event log. These operations will need to be stored and sent to validators.
  • After executing this code, the garbage contract sayHello will appear in the Rspace, and this garbage will lie in the Rspace forever.
  • ???

Illustrative example 2

Hardworking programmer

Now I want to add 10 elements to the collection:

new mySet in {
    mySet!(Set().add(10).add(9).add(8).add(7).add(6).add(5).add(4).add(3).add(2).add(1))
}

It's requered only 1 sending, 1 record in eventlog and one data in RSpace(more or less like this).

Lazy programmer

But I'm a lazy programmer and don't really like copy-paste. Therefore, I would like to write.

new mySet, loop in {
  contract loop(@n, @acc) = {
    if (n == 0) mySet!(acc)
    else loop!(n - 1, acc.add(n))
  } |
  loop!(10, Set())
}
  • I do the same:
    mySet!(Set().add(10).add(9).add(8).add(7).add(6).add(5).add(4).add(3).add(2).add(1))
  • But I spend 10 times more resources on it. And I create garbage in RSpace.
  • ???

Local contracts is the solution! (?)

Why not let the user decide for himself what data he wants to write on the blockchain and what not?

new сhat in {
      local contract sayHello(@name) = {сhat!("Hello, " ++ name ++ "!!!")}
    | sayHello!("Stas") | sayHello!("Tomislav") | sayHello!("Anton")
}
new mySet in {
  local contract loop(@n, @acc) = {
    if (n == 0) mySet!(acc)
    else loop!(n - 1, acc.add(n))
  } |
  loop!(10, Set())
}

During rholang interpretation, contracts labeled as local will be expanded and converted to rolang code without garbage helper functions.

Also similar contracts can be used to store local Vals along with let.

Of course we must make rules for such contracts, for example:

  • The description of the contract must be in the deploy.
  • The description of the contract must be passed to the validator along with the rholang code.
  • If a local contract import from a library is used, this library must be synchronized with the validators.
  • Calling a local contract must provide the same charging on all nodes.
  • ...

Conclusion

In order for rolang to be used effectively for data processing, we must implement a fast preprocessing mechanism.
There are two ways how to do it:

  • Third-party code
    • Rholang is used for work with RSpace.
    • For work with data in RAM third-party code is used (scala, java, c++, etc.)

We do not go this route, as it requires the support of a third-party programming language on all nodes. And we want to have a cross-platform solution.

  • Local contracts
    This is the same as the first way, but we write third-party code in Rholang

@hilltracer Please add to the description how your suggestion can be used to write helper libraries like ListOps. You can try to implement one method like map or fold.