Skip to content

Commit

Permalink
Paris support - fix #703 (#704)
Browse files Browse the repository at this point in the history
* Paris support - fix #703
  • Loading branch information
nicolasochem authored Jun 28, 2024
1 parent ae2c50f commit 091d406
Show file tree
Hide file tree
Showing 65 changed files with 202 additions and 1,745 deletions.
5 changes: 0 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,6 @@ jobs:
python -m pip install -r requirements.txt
python -m pip install -r requirements_developers.txt
- name: Test with pytest
env:
TZPRO_API_KEY: ${{ secrets.TZPRO_API_KEY }}
run: pytest tests/

build-documentation:
runs-on: ubuntu-latest
strategy:
Expand Down
6 changes: 1 addition & 5 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,12 @@ Available configuration parameters are:
There are two options for calculating the total rewards earned by a baker at the end of each cycle. If this parameter is missing, 'actual' rewards take affect.

- 'actual': Rewards are calculated based on the actual number of bakes, at any round. Transaction fees, bonuses and other block rewards are included in the rewards when earned. If a bake is missed, rewards are not earned and therefore not included. If endorsement rewards are not earned due to a failure to reveal a nonce or excessive unavailability of your baker, is it not included.
- 'ideal': Rewards are calculated assuming ideal behavior of the baker, and actual behavior of other bakers. If a bake is missed, 20 tez rewards are paid out despite not having been earned. If a round 0 payload has been produced, but another baker baked the block, the missed bonus is **not** paid out, because it is due to other bakers being offline and not endorsing. Transaction fees, bonuses and other block rewards are included in the rewards. The endorsing reward is paid out even in case it has not been earned. Select this type of rewards to insure against downtime of your baker but still account for real world conditions. This way, you will get optimal ranking in baker evaluation services despite any downtime.
- 'ideal': Deprecated.

Example::

rewards_type: actual
Note::
Providing '--adjusted_early_payouts' will trigger estimated payouts which are adjusted later on. See: :ref:`payout_timing`

**service_fee**
A decimal in range [0-100]. Also known as the baker's fee. This is evaluated as a percentage value. Example: If set to 5, then 5% of baking rewards are kept as a service fee by the baker.

Expand Down
18 changes: 6 additions & 12 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ PRIVACY : TEZOS REWARD DISTRIBUTOR COLLECTS ANONYMOUS STATISTICS. PLEASE READ OU
What's TRD?
------------------------------------------------

TRD is an open-source software for distributing staking rewards from bakers to delegators introduced in detail in this Medium article_. This is not a python script but a full scale application which can continuously run in the background as a Linux service. However it does not have to be used as a service, but it can also be used interactively. The tool convinces with its simplicity and yet leaves no configuration wish unfulfilled. Whether minimum delegation threshold, special fees for some delegators, or actual vs ideal rewards - the TRD covers just about all possible constellations. Furthermore, the tool supports complex payments, pays in batches, and provides three back ends for calculations: Tezos RPC, tzpro_ API and TzKT_ API. TRD is developed and tested extensively by the community and the source code which can be found in the following Github_ repo.
TRD is an open-source software for distributing staking rewards from bakers to delegators introduced in detail in this Medium article_. This is not a python script but a full scale application which can continuously run in the background as a Linux service. However it does not have to be used as a service, but it can also be used interactively. The tool convinces with its simplicity and yet leaves no configuration wish unfulfilled. Whether minimum delegation threshold, or special fees for some delegators - the TRD covers just about all possible constellations. Furthermore, the tool supports complex payments, pays in batches. It uses TzKT_ API as backend. TRD is developed and tested extensively by the community and the source code which can be found in the following Github_ repo.

Tezos offers two kind of rewards: delegating rewards and staking rewards. TRD pays out delegation rewards. Staking rewards are paid by the protocol, and TRD does not concern itself with them.

Who needs TRD?
------------------------------------------------
Expand All @@ -22,25 +24,17 @@ What else do you need for TRD?

There are currently the following options to run TRD:

a. If you want to use RPC (not public RPC) for the reward calculation, you need a Tezos archive node.
b. If you want to use an provider (pRPC, TZPRO, tzkt) for the reward calculation, but want to inject your own transactions, at least a Tezos rolling node is needed.
c. If you want to use an provider (pRPC, TZPRO, tzkt) for the reward calculation and don't want to inject your own transactions, only the Tezos signer is needed.
a. If you want to inject your own transactions, at least a Tezos rolling node is needed.
b. If you don't want to inject your own transactions, only the Tezos signer is needed.

However, for all options the Tezos signer is needed.

**Provider notes:**

Blockwatch: TZPRO
------------------

The terms_ of TZPRO note that an account and API key are needed for the use of the API. Please review the [pricing](https://tzpro.io/#pricing) information. For further help contact [email protected] for more information.

In order to use your API key in the application add it to your configuration like tzpro_api_key: XXXXXXXXXX.

TzKT
-----------

With PR232_ the backend of the Tezos Reward Distributor can be optionally `Powered by TzKT API`__ under the following terms:
The backend of the Tezos Reward Distributor is `Powered by TzKT API`__ under the following terms:

TzKT API is free for everyone and for both commercial and non-commercial usage.

Expand Down
72 changes: 2 additions & 70 deletions docs/payouttiming.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,78 +7,10 @@ Tezos rewards are paid out by the protocol at the end of a given cycle.

By default, TRD then distributes these rewards at the beginning of the next cycle.

Bakers may elect to pay their delegators early to appear more
competitive or trustworthy. But bakers paying early effectively give an “advance” to their delegators.
This means that they have a lower balance at any given point in time.

TRD behavior is to pay out the last released payment cycle. Last
released payment cycle will be calculated based on the formula:
``current_cycle - 1 + [if --adjusted_payout_timing is provided: (preserved_cycles + 1)]``.

A cycle on mainnet lasts 3 days.

The ``--adjusted_early_payouts`` argument lets the baker override when rewards
are released (paid out). Its default value is ``False`` if not provided as argument.

Possible choices are:

- ``not provided``: pay rewards after the cycle runs - 6 to 7 cycles after delegation. The recommended default choice.
- ``--adjusted_early_payouts``: pay rewards when baking rights are assigned, referred as “adjusted early payouts” (see below) - 1 to 2 cycles after delegation.

Adjusted early payouts
----------------------

Providing ``--adjusted_early_payouts`` as additional argument will trigger adjusted early payouts.

When selected, this option calculates and pays out the expected rewards based on baking and
endorsing rights only. It does not takes into account fee income,
denunciation income or rescued block income. It also assumes perfect
behavior of the baker and other bakers.

The resulting rewards are thus an estimation. When the cycle
actually runs, TRD runs the calculations for this cycle again, based on
the rewards type configured (ideal or actual). It then computes the
“overestimate” or overpaid value.

TRD then attempts to claim back this overestimate by adjusting the
amount paid. **This does not always work**. If the delegator has emptied
their account or changed delegate, there is no longer any payout to
offset a past overestimate. Thus, users are advised caution when using
this feature.

The estimate can also be lower than the final amount, for example if fees were earned in excess of the missed income, or if blocks have been rescued by the baker. In this case, the overestimate will show a negative amount, the delegator has been underpaid and will be compensated with a positive adjustment.

Overestimate, adjustment and adjusted amount paid can be seen in the
calculations CSV file.

**Example:**

**Cycle 100**: Frank and Cindy both delegate 1000 tez to Jane’s bakery. For
simplicity, Jane’s bakery has no fee and no other delegators. Her bakery is
configured with a ``--adjusted_early_payouts`` and ``rewards_type`` ``actual``.

**Cycle 103**: Since ``--adjusted_early_payouts`` is provided as argument, payout for cycle 108 happens during cycle 103. Frank and Cindy’s delegation is taken into account to compute
cylce 108’s rights. Jane’s bakery is expected to earn 80 tez rewards for
cycle 108 from baking and endorsing rewards. Frank and Cindy contribute 10% each to Jane’s staking
balance. They each receive 8 tez as part of the payout for cycle 108.

A ``calculations/108.csv`` file is generated which shows ``Overestimate:
pending`` as cycle 108 has not run yet.

**Cycle 104-108**: same as cycle 103: Frank and Cindy receive 10% each of the estimated reward.

**Cycle 109**: Jane’s bakery is expected to earn 60 tez from baking and endorsing rewards for cycle 114, so
each delegator should be paid 6 tez. TRD runs the calculations for
cycle 108 again and finds that Jane earned 0.5 tez fee for baking a
block, and failed to bake the other block, a loss of 20 tez.
Overall, Jane’s bakery overestimated its earnings by 19.5 tez.
It therefore subtracts 1.95 tez of cycle 108 payout to cycle 114 payout (which happens at cycle 109).
Frank and Cindy receive 4.05 tez as adjusted amount for cycle 114.

``calculations/108.csv`` file is updated with a total overestimate of 19.5
and their distribution across delegates: 1.95 tez for Frank and for
Cindy. ``calculations/114.csv`` file mentions an adjustment of 1.95 tez for
Frank and Cindy.
A cycle on mainnet lists 3 days.

Had Frank left the bakery at cycle 104, Jane’s bakery would have been
unable to recover his overpaid 1.95 tez.
Delegation takes 2 cycles to take effect. This is unlike staking, which is instantaneous.
2 changes: 2 additions & 0 deletions src/Constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@

FIRST_MUMBAI_LEVEL = 3268609

FIRST_PARIS_LEVEL = 5726209

TEZOS_RPC_PORT = 8732

SIGNER_PORT = 6732
Expand Down
6 changes: 3 additions & 3 deletions src/Dexter/dexter_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def get_dexter_balance_map(contract_id, snapshot_block, api_provider):
def process_original_delegators_map(
delegator_map, contract_id, snapshot_block, api_provider
):
contract_balance = delegator_map[contract_id]["staking_balance"]
contract_balance = delegator_map[contract_id]["delegating_balance"]
dexter_liquidity_provider_map, totalLiquidity = get_dexter_balance_map(
contract_id, snapshot_block, api_provider
)
Expand All @@ -34,10 +34,10 @@ def process_original_delegators_map(
/ totalLiquidity
)
if delegator in delegator_map:
delegator_map[delegator]["staking_balance"] += balance
delegator_map[delegator]["delegating_balance"] += balance
else:
delegator_map[delegator] = {}
delegator_map[delegator]["staking_balance"] = balance
delegator_map[delegator]["delegating_balance"] = balance
delegator_map[delegator]["current_balance"] = dexter_liquidity_provider_map[
delegator
]["current_balance"]
Expand Down
5 changes: 4 additions & 1 deletion src/api/block_api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from abc import ABC, abstractmethod
from Constants import FIRST_GRANADA_LEVEL, FIRST_MUMBAI_LEVEL
from Constants import FIRST_GRANADA_LEVEL, FIRST_MUMBAI_LEVEL, FIRST_PARIS_LEVEL

# TODO: we should check if we are on mainnet, or a testnet
# we could add a get_current_protocol() method and check against it
Expand All @@ -15,6 +15,9 @@ def get_current_cycle_and_level(self):
pass

def level_in_cycle(self, level):
if level >= FIRST_PARIS_LEVEL:
# Since protocol Paris
return (level - FIRST_PARIS_LEVEL) % self.nw["BLOCKS_PER_CYCLE"]
if level >= FIRST_MUMBAI_LEVEL:
# Since protocol Mumbai
return (level - FIRST_MUMBAI_LEVEL) % self.nw["BLOCKS_PER_CYCLE"]
Expand Down
33 changes: 2 additions & 31 deletions src/api/provider_factory.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
from rpc.rpc_block_api import RpcBlockApiImpl
from rpc.rpc_reward_api import RpcRewardApiImpl
from blockwatch.tzpro_block_api import TzProBlockApiImpl
from blockwatch.tzpro_reward_api import TzProRewardApiImpl
from tzkt.tzkt_block_api import TzKTBlockApiImpl
from tzkt.tzkt_reward_api import TzKTRewardApiImpl
from Constants import PUBLIC_NODE_URL


class ProviderFactory:
Expand All @@ -20,22 +15,7 @@ def newRewardApi(
api_base_url=None,
tzpro_api_key="",
):
if self.provider == "rpc":
if node_url.find("http") == -1:
node_url = "http://" + node_url
return RpcRewardApiImpl(network_config, baking_address, node_url)
elif self.provider == "prpc":
if node_url_public == "":
node_url_public = PUBLIC_NODE_URL[network_config["NAME"]]
return RpcRewardApiImpl(network_config, baking_address, node_url_public)
elif self.provider == "tzpro":
return TzProRewardApiImpl(network_config, baking_address, tzpro_api_key)
elif self.provider == "tzkt":
return TzKTRewardApiImpl(
network_config, baking_address, base_url=api_base_url
)

raise Exception("No supported reward data provider : {}".format(self.provider))
return TzKTRewardApiImpl(network_config, baking_address, base_url=api_base_url)

def newBlockApi(
self,
Expand All @@ -44,13 +24,4 @@ def newBlockApi(
api_base_url=None,
tzpro_api_key="",
):
if self.provider == "rpc" or self.provider == "prpc":
if node_url.find("http") == -1:
node_url = "http://" + node_url
return RpcBlockApiImpl(network_config, node_url)
elif self.provider == "tzpro":
return TzProBlockApiImpl(network_config, tzpro_api_key)
elif self.provider == "tzkt":
return TzKTBlockApiImpl(network_config, base_url=api_base_url)

raise Exception("No supported reward data provider : {}".format(self.provider))
return TzKTBlockApiImpl(network_config, base_url=api_base_url)
Empty file removed src/blockwatch/__init__.py
Empty file.
37 changes: 0 additions & 37 deletions src/blockwatch/tzpro_api_constants.py

This file was deleted.

67 changes: 0 additions & 67 deletions src/blockwatch/tzpro_block_api.py

This file was deleted.

Loading

0 comments on commit 091d406

Please sign in to comment.