Skip to content
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

Protocol version 7 update proposal #64

Merged
merged 8 commits into from
Jun 25, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
320 changes: 320 additions & 0 deletions updates/P7.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,320 @@
Protocol update

Protocol Version: 7
Builds on Protocol Version: 6

Abstract

This document describes the changes in Concordium protocol version 7 compared to
protocol version 6.

The protocol change has the following main effects
- redefines smart contract costs, reducing the cost of smart contract calls;
- adds support for querying the module reference and contract name of a smart
contract instance in smart contracts;
- changes cooldown behavior so that:
* when validators and delegators reduce their stake, the reduction is
immediately effective for future stake calculations, and the amount of the
reduction is looked for a cooldown period;
* validators and delegators can make further changes to their stake while
they already have stake in cooldown;
- disallows shielded (or encrypted) transfer transactions (`TransferToEncrypted`,
`EncryptedAmountTransfer` and `EncryptedAmountTransferWithMemo`).

Background

Smart contract execution costs are reduced in protocol version 7 because of
efficiency improvements in the implementation of smart contract execution.
The revised cost model is based on an execution model where the interpreter
stack is compiled to registers.

The new protocol version also imposes a limit on the nesting depth of
inter-contract calls to 384. This is since each live execution frame can
require up to 32MB of memory, so limiting the number of active execution
frames in this way safeguards against excessive memory use.

* * *

As of protocol version 7, smart contracts are able to query the module
reference and contract name of a smart contract instance. This can be used
to identify the code that is behind a smart contract instance, for example as
a means of authenticating a smart contract before interacting with it. A
particular motivation for this is to implement a factory pattern, where one
smart contract (the factory) is responsible for initializing instances of
another (the product). On Concordium, one smart contract cannot directly
create instances of another, but it can be used to invoke an initialization
method on another. The additional queries allow the factory to ensure that
the contract instance it is initializing is of the correct type.

* * *

Prior to protocol version 7, when a validator or a delegator reduces or
removes its stake, the amount of the stake reduction is held in a cooldown
state. During the cooldown period, the stake cannot be spent, and remains
part of the effective stake (used for lottery and reward calculation). Once
the cooldown period has elapsed, the stake is available to be spent, and
no longer contributes to the effective stake of the baker or delegator.
While the cooldown is in effect on an account, no other changes can be made
to the account's stake.

From protocol version 7, when a validator or delegator reduces its stake,
the stake reduction takes effect straight away, but the amount of the
reduction enters a cooldown queue. (Note that "straight away" here does
not mean that is has an instant effect on the lottery and rewards. The
effective stakes of bakers and delegators are sampled in the first block
of the last epoch before each payday, with the sampled stakes being used
from the upcoming payday. Although the change is recorded on the account
immediately, it will be between 1 epoch and 1 payday plus 1 epoch until
the change affects the proof-of-stake lottery used for consensus.)
Stake in the cooldown queue is considered to be inactive stake, and, as
such, does not contribute to the lottery calculation. However, the
inactive stake still cannot be spent, although it is possible to transfer
it back to active stake.

When stake is removed from a validator or delegator, it enters cooldown
at the point that the removed stake is no longer part of the effective
stake for lottery calculations. Specifically, when the stake is removed,
it first enters a "pre-pre-cooldown" state. When the stake snapshot is
taken for next payday (in the first block of the epoch before the payday)
it is moved from "pre-pre-cooldown" to "pre-cooldown". At the subsequent
payday, it is moved from "pre-cooldown" into "cooldown", and the cooldown
expiry time is set based on the cooldown time chain parameter. In
particular, the cooldown officially starts at this payday. At the first
payday at or after the cooldown expiry time, the stake finally exits
"cooldown" and becomes available to spend. An account's active stake
can be reduced while there is still inactive stake in cooldown, leading
to multiple amounts in cooldown (or pre-cooldown or pre-pre-cooldown)
that expire at different times.

If the active stake on an account is increased, the increase is first
transferred from the inactive stake in preference to taking from the
unstaked balance. Specifically, it is taken first from "pre-pre-cooldown",
then "pre-cooldown", and then from the "cooldown" stakes in decreasing
order of expiry time. An account can also switch freely between being
a validator and being a delegator without its stake entering cooldown.
(Prior to protocol version 7, it was necessary to remove the validator
or delegator on an account, waiting out the cooldown period, before
instating a delegator or validator.) As a consequence of this, from
protocol version 7, no distinction is drawn between the cooldown time
for validators and for delegators: stake entering cooldown expires
after the minimum of both times.

The purpose of these changes is to maximise the flexibility of staking,
while still ensuring that any stake must still be locked for the
cooldown period before it can be spent.

* * *

Since the initial protocol version, the Concordium block chain has
supported shielded transfers (also known as encrypted transfers).
This mechanism allows an account to "shield" part of its balance,
cryptographically encrypting it so that the amount cannot be inspected
except by the owner of the account (using its secret encryption key).
An account can transfer an amount from its shielded balance to another
account. While the sender and receiver are publicly visible, the exact
amount transferred (in CCD) is not. An account can also decrypt funds from
its shielded balance, enabling them to be spent as normal. Each of
these operations makes use of zero-knowledge proofs to ensure that
the transfers are carried out correctly (i.e. without creating or
destroying any CCDs) while not revealing the encrypted values.

This feature has not seen widespread use. Moreover, the presence of
shielded transfers is seen as a barrier to adoption of Concordium
by some risk-averse parties. As such, the shielded transfers are
no longer supported as of protocol version 7.

In particular, shielding (or encrypting) a public balance and
transferring shielded funds from one account to another are
disallowed from protocol version 7. Unshielding (i.e., transferring
funds from an account's shielded funds to its own unshielded funds)
remains enabled. This ensures that accounts do not simply lose any
funds that they previously shielded.

Changes

The following behaviors are changed in protocol version 7.

1. The cost metering for smart contract execution is redefined. The new
instruction costs of WebAssembly instructions are defined below.
(1 Energy = 1000 Interpreter Energy.)

Instruction Old cost (Interpreter Energy) New cost (Interpreter Energy)

nop 1 1
unreachable 0 0
block 0 0
loop 0 0
if 10 4
br 8 + target arity (0 or 1) 2
br_if 10 4
br_table 10 + target arity 7
return 8 + return arity 2
call 26 + #arg + #res 6 + #arg + #res
call_indirect 28 + 2*(#arg + #res) 8 + |_ 1.1*(#arg + #res) _|

drop 2 0
select 3 2

local.get 3 0
local.set 3 0
local.tee 3 0
global.get 3 1
global.set 3 1

inn.load* 4 1
i32.store 8 2
i64.store 10 2
i32.store8 5 2
i32.store16 8 2
i64.store8 7 2
i64.store16 9 2
i64.store32 10 2
memory.size 4 1
memory.grow 10 + 100 * #pages 10 + 100 * #pages

inn.const 2 0
inn.eqz 3 1
inn.clz 3 1
inn.ctz 3 1
inn.popcnt 3 1
inn.eq 4 1
inn.ne 4 1
inn.lt* 4 1
inn.gt* 4 1
inn.le* 4 1
inn.ge* 4 1
inn.add 4 1
inn.sub 4 1
inn.mul 5 2
inn.div* 5 2
inn.rem* 5 2
inn.and 4 1
inn.or 4 1
inn.xor 4 1
inn.shl 4 1
inn.shr* 4 1
inn.rotl 4 1
inn.rotr 4 1
i32.wrap_i64 3 1
inn.extend* 3 1

(Here, target arity and return arity are the arity of the target
label and the current activation frame respectively; #arg and
#res are the numbers of arguments and results of the function
being called; and #pages is the number of memory pages requested
by memory.grow.)

The cost (in Energy) of looking up a contract module is reduced from
|_ size / 50 _| to |_ size / 500 _|, where size is the size of the
module's WebAssembly source in bytes, not including custom sections.
This cost is incurred on contract initialization, update, upgrading and
inter-contract calls.

2. The maximum nesting depth of V1 contract calls is limited to 384.

3. In V1 smart contracts, the `invoke` operations allows for two
additional operations:

- Query smart contract module reference:
* Instruction tag: 7
* Payload:
- contract index (8 bytes, little endian)
- contract subindex (8 bytes, little endian)
* Return codes:
- 0: success
the return value is the module reference of the specified
contract instance
- 3: missing contract
there is no contract instance with the given address
* Cost: 200 Energy
- Query smart contract name:
* Instruction tag: 8
* Payload:
- contract index (8 bytes, little endian)
- contract subindex (8 bytes, little endian)
* Return codes:
- 0: success
the return value is the name of the `init` method used to
create the contract instance (including the "init_" prefix)
- 3: missing contract
there is no contract instance with the given address
* Cost: 200 Energy

4. The following changes apply to staking:
- The stake of an account is divided into
* Active stake: this determines the baker or validator's
stake for future snapshots that determine the stake
distribution for the purposes of lottery calculation and
reward distribution.
* Inactive stake: this does not contribute to lottery or
reward calculations, but is locked for a period of time.
The inactive stake can consist of multiple amounts that
can be in the following states:
- cooldown with a specific expiry time
- pre-cooldown
- pre-pre-cooldown
- When a validator or delegator is removed from an account, the
validator or delegator record is removed from the account and
the active stake is moved to the inactive stake in the
pre-pre-cooldown stake.
- When a validator or delegator has its stake reduced, the amount
of the reduction is moved to the inactive stake in the
pre-pre-cooldown stake.
- When a validator or delegator has its stake increased (including if
an account becomes a validator or delegator when it was neither),
the amount of the increase will be taken preferentially from
inactive stake in the the following order:
* pre-pre-cooldown
* pre-cooldown
* cooldown (starting from the highest expiry timestamp)
- A validator or delegator may switch to the other role at any time
(by a `ConfigureBaker` or `ConfigureDelegator` transaction). It is
only subject to cooldown in this process insofar as the stake is
reduced.
- At the first block in an epoch, the following occur:
* If the epoch is the first of a new payday (a payday epoch) then
all amounts in cooldown that are set to expire at or before the
transition time for the previous epoch (the payday time) are
released from the inactive stake of accounts. All amounts in
pre-cooldown are moved into cooldown, with the expiry time set
to be the minimum of the current validator and delegator cooldown
time parameters (accounting for any parameter changes up to the
current block) after the payday time.
[Note: as before, at payday the current epoch stakes and capital
distribution are updated based on the snapshot taken in the
previous epoch, and all rewards are paid out that have accrued.]
* If the epoch is the last before a new payday (a snapshot epoch)
then all amounts in pre-pre-cooldown are transferred to pre-cooldown.
[Note: as before, in a snapshot epoch, the snapshot of the stakes
and capital distribution is taken for the next payday.]

5. The transaction payload types `TransferToEncrypted`,
`EncryptedAmountTransfer` and `EncryptedAmountTransferWithMemo` are
considered invalid. Transactions of these types will be rejected with
a `SerializationFailure` result.

Effects

1. At the protocol update, the following changes apply to validator and
delegator accounts:
* If the account was pending cooldown, it is removed from
the pending state and the amount of the reduction in stake will be moved
from its active stake to the pre-pre-cooldown inactive stake.
* If the account was pending removal (of the validator or delegator),
the validator or delegator record is removed from the account and the
active stake is moved to the pre-pre-cooldown inactive stake.

2. Behavior of existing V1 contract instances may be affected in the
following scenarios:
- The cost of smart contract execution is changed as described above.
- If the contract execution exceeds a nesting depth of 384 contract
calls, the execution will fail.
- If the contract uses the `invoke` operation with tags 7 or 8, prior
to the update a runtime error would be triggered; after the update
the behavior will be as defined above (querying the module reference
or name).

Protocol update instruction

The protocol update instruction is identified by the SHA256 hash of
this file. There is no auxiliary data for the update instruction.
Loading