In our last post Problems with Balance, we described problems with the way
Balance is calculated due to the BFS calling pattern in Tezos.
Balance does not take into account a contract’s expected
Incoming funds from operations later in the operation queue than the currently executing operation, and it does not take into account
Outgoing funds already promised by the currently executing contract in operations in the queue that have not yet been executed. Here, we will propose a solution to this problem along with the minimum changes to the Tezos architecture the solution requires.
Each contract will get a new storage variable:
Outgoing. This does not require changes to Tezos architecture, just changes to the way Contracts are written. Tezos will maintain a global map
Incoming : Contract –> Tezas it does
Balance(this requires changes to Tezos architecture).
Everytime a contract adds a transfer operation to its operation queue, it will also add the amount transferred in that operation to its storage variable
Suppose Contract A invokes Contract B m times and each for invocation i of Contract B, B generates n transactions ti1, …, tin (where operation tij transfers A(tij) to T(tij)). Then, Tezos will make the following changes to how these n*m transactions are executed.
- Before any of these n*m transactions are executed, for all i,j Tezos will execute II(tij) (or Increase Incoming) which will add A (tij) to Incoming(T(tij)).
- For all i,j, for a given tij Tezos will generate another operation DI(tij) (or Decrease Incoming). DI(tij) will subtract A (tij) from Incoming(T(tij)). DI(tij) will execute immediately after tij executes.
- For all i,j, for a given tij Tezos will generate another operation DO(tij) (or Decrease Outcoming). DO(tij) is a self call that will subtract A(tij) from its own
Outgoingstorage variable. DO(tij) will execute immediately after DI(ij) executes.
NOTE: For simplicity, points 1 and 2 in the list above are written to look like we are adding new operations to the operation queue. In reality these ‘operations’ just indicate a change in the way Tezos processes operation queues. Point 3 in the above list is indeed a new operation added to the operation list that could be implemented by contracts without changes to the tezos architecture. However, since 1 and 2 require changes to Tezos code, we suggest that point 3 is implemented by Tezos as well.
Each contract can now get a new storage variable
EffectiveBalance := Balance + Incoming - *Outgoing - Transferred(where we derefence a pointer to Outgoing so that changes to it in that contract’s code will be reflected in EffectiveBalance.
Transferredrefers to what is currently returned by
AMOUNTopcode and is subtracted from calculation to correct for double counting of
Required Changes to Tezos Architecture
- Creation and maintenance of external map
Incoming : Contract –> Tez, similar to existing one
Balance.NOTE: In contrast to
Incoming,a given contract’s
Outcomingbalance can be maintained as a storage variable in that contract, and does not require changes to Tezos architecture. However, that contract cannot know the amount being sent to it by another contract and we cannot rely on/trust external callers to accurately report the total amount they are sending to another contract across all operations. Therefore,
Incomingmust be maintained by Tezos.
- A new Opcode
INCOMINGwhich returns the calling contract’s expected incoming funds at time of execution.
- Changes to the Tezos scheduler that implement the solution described in point 3 of the above section.