-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Seal: Scratch away the scratch buffer (Part 1) #5513
Comments
Totally makes sense. Very nice. |
I am in strong favor of this proposal. The scratch buffer abstraction is neither easy to use nor does it provide performance benefits in those cases. It is the worst of both worlds. In this spirit I am in favor of the approach with the in/out argument which saves one parameter. At this level it should not be about what is most easy to use but what is the simplest solution that maintains minimal overhead. In this sense the additional argument is redundant in that it only provides some protection against footgunning. This should be provided by a layer on top this API (ink!, solang). |
When This also reduces the code and calls needed. |
The problem with calls like While I believe that we can also find solutions for costly calls such as However, I think we should first get this part 1 of "scratching away the scratch buffer" done and then collect thoughts and ideas in a part 2. |
You're assuming that account ID can be of a non-fixed length type? Is this already the case, or is this for future-proofing the interface? |
Yes, as with other |
Background
This issue introduces an incremental redesign of parts of the interface between the contracts pallet and WebAssembly smart contracts.
A similar discussion has already been started some time ago but in the end was not targeted enough and not chunked up into actionable work items. This issue is the beginning of a potential series of issues that chunk up the massive work needed to get the interface into an efficient and nice shape.
Motivation
The current problem with certain parts of the interface is two fold.
ext_
hashes we have already taken an approach of avoiding the scratch buffer in their interfaces. So going down this path for other APIs does not introduce another unknown API style.Example
Current Interface
Let us look at an example of the current API, line out the problems with it and propose another interface that fixes those outlined problems with the same example.
We are going to take a look at a common invocation of the
ext_caller
API.This extracts information about the
AccountId
of the caller of the currently running smart contract execution.The procedure is as follows:
ext_caller
to make the host side put the information into the scratch buffer.ext_scratch_size
.ext_scratch_read
.In code this looks similar to this:
This incorporate 3 mandatory calls between contract and pallet.
Also it has the huge disadvantage of the shared mutable state on the pallet side which is hidden from the contract and would cause trouble if there was a call to another
ext_
function somewhere in between for example.Proposed Interface
This issue proposes to change the API to no longer require 3 calls but instead a single call between contract and pallet. The API for
ext_caller
looks like the following:Where
(output_ptr, output_len)
represents a contract-side buffer where the result ofext_caller
is to be stored ifoutput_len
suffices the requirements andoutput_req_len
is an out-parameter to be set by the pallet that tells the contract side how many bytes have actually been used byoutput
sinceoutput_len
could in theory be equal to or greater than the actually required bytes.Returns
0
upon success or1
ifoutput_len
is too small to hold the result.In this case the contract side needs to handle the error e.g. by increasing the buffer size and do the call again. This second call is obviously "bad" however, given that entities such as ink! or Solang are aware of the issues this case would potentially never really happen since the
output
buffer would simply be big enough for all use cases. So the API optimizes for the happy path.Let us look how the call to this new
ext_caller
API would look like:Note that in the worst case exactly two calls to
ext_caller
are issued: If the first call provided anoutput
buffer that was too small the contract still receives the required length of theoutput
buffer via thereq_len
output-parameter back and can adjust its output buffer size.Alternative Design
A slight alteration of the proposed design is to merge
output_len
input parameter andoutput_req_len
output parameter:This has the advantage of getting rid of a single parameter but has the downside of making the calling process a bit harder and callers have to take extra care not to accidentally mutate state of their internal data structures.
Proposal
This issue proposes to apply the above presented API change not only to
ext_caller
but to all property-like APIs currently existing in the contracts pallet interface for smart contracts.This includes but is not limited to:
ext_caller
ext_address
ext_gas_price
ext_gas_left
ext_balance
ext_value_transferred
ext_now
ext_minimum_balance
ext_tombstone_deposit
ext_rent_allowance
ext_block_number
Future Work
In the future we are trying to apply scratch buffer avoiding interfaces to other APIs in the contracts pallet. We could do this for the majority or even all APIs. However, we have to solve the problem of potentially expensive calls such as
ext_call
that might explode in costs (gas costs) if called multiple times in case the givenoutput
buffer was too small.The ultimate goal is to completely get rid of the explicit notion of a scratch buffer in the interfaces. However, due to open questions as the one stated above we opted in to make these changes incremental instead of bulk.
The text was updated successfully, but these errors were encountered: