Skip to content

Conversation

@nkuba
Copy link
Member

@nkuba nkuba commented Mar 29, 2022

Refs: #2850
Closes: #2715
Depends on: #2906

This PR integrates Random Beacon with Threshold Network TokenStaking contract.

It implements functions to let the operator join the sortition pool and update its status in the sortition pool. StakingStub contract has been removed and all tests operate on a real T TokenStaking now.

The changes were already implemented in ECDSA Wallets in #2850 and this PR is based on it.

Operators To Staking Providers Mapping

Please note that due to 8e9b2a4 a gas cost of executing functions that call seize and slash grew significantly:

        method            |   min   |   max   |   avg
-------------------------------------------------------
submitRelayEntry          | 213867  | 3693768 | 1760490 
reportRelayEntryTimeout   | 3641465 | 3659466 | 3654018
reportUnauthorizedSigning |    -    |    -    | 3774342

@nkuba nkuba requested review from dimpar and pdyraga March 29, 2022 10:29
@nkuba nkuba force-pushed the random-beacon-t-staking-integration branch from 05ec8a2 to 8436925 Compare March 29, 2022 15:04
nkuba added 11 commits March 30, 2022 14:51
We integrate RandomBeacon application with TokenStaking contract defined
for Threshold Network.

The source code is copied from work that was already done for ECDSA
Wallets in #2850
We don't want to validate TokenStaking size as it's an external
contract that we expect to be deployed separately.
TokenStaking contract expects amounts for slashing to be uint96. This is
size of number exceeds the T token total supply enyways and is so big
that will fit the slashing amount for sure.
Compile dependencies from external package to use in deployment and
tests here.
We will use actual T token implementation instead of this TestToken.
Stores ethers Signer in the Operator instead of just an address to
simplify usage.
We use minimumAuthorization parameters instead which is an application
specific parameter.
We integrated with TokenStaking defined in Threshold Network's
contracts so we can switch our tests to use the proper contracts.

We use hardhat deployment fixture `TokenStaking` that is defined in
@threshold-network/solidity-contracts to simplify deployment of
contracts for tests.
The tests are covered byt the Authorization tests.
@nkuba nkuba force-pushed the random-beacon-t-staking-integration branch from 8436925 to 043a28f Compare March 30, 2022 12:52
@nkuba nkuba changed the base branch from main to beacon-stub-improve March 30, 2022 12:53
@nkuba nkuba mentioned this pull request Mar 30, 2022
nkuba added 10 commits March 30, 2022 15:20
TokenStaking contract operates on staking providers addresses. Group
members are operators that are internal to RandomBeacon application. We
need to map operator addresses to staking provider addresses for seize
and slash functions calls.
To have the tests that are more reliable we neeed to ensure unique
address is used for each of the roles registered in Token Staking.
We need an unique address for 64 group members for each role: owner,
staking provider, operator, beneficiary and authorizer.

We introduced `unnamedSignersOffset` to specify from which unnamed
signer account we should start obtaining signers. This is for a case
where we want to pull some other accounts e.g. for third party and
don't want to overlap.
getUnnamedSigners returns a signer so it simplifies the way we want to
obtain the signer.
It's easier to modify the value in parameters without having to update
all the hardcoded places.
We don't want to error on this check.
Our contracts grew to the point where a RandomBeaconStub is problematic to deploy.
The RandomBeacon size is fine though.

We can safely ignore contract size on deployment in hardhat network as
contract size is verified by `contractSizer` and it will alert us if any
of the contracts is too big.
We want to have unique signers for operators registration for each of 5
roles. This requires hardhat network configuration account count to be
aligned. We want to ensure the configuration is correct and output a
meaningfull error if it's not. Without that the test execution fails
with an error that doesn't give much clue.
nkuba added 3 commits March 31, 2022 17:23
The rewards are calculated based on the multiplier and queue of slashed
staking providers. We fix how the expected value is calculated.
We set minimumAuthorization to a value different than
unauthorizedSigningSlashingAmount to not have false positive results in
tests when the parameters would be confused.
Copy link
Member

@pdyraga pdyraga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First round, more to come.

.getIDOperators(groupMembers);

try staking.slash(slashingAmount, groupMembersAddresses) {
address[] memory stakingProvidersAddresses = new address[](
Copy link
Member Author

@nkuba nkuba Apr 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to extract this piece of code to the Authorizations library (code snippet below) to reduce transaction costs, but unfortunately, it ended up being even more expensive:

        method            |   min   |   max   |   avg
-------------------------------------------------------
submitRelayEntry          |  213867 | 3735913 | 1779221 
reportRelayEntryTimeout   | 3683609 | 3701610 | 3696162
reportUnauthorizedSigning |    -    |    -    | 3816486
    function operatorsToStakingProviders(
        Data storage self,
        address[] memory operators
    ) external returns (address[] memory) {
        address[] memory stakingProviders = new address[](operators.length);
        for (uint256 i = 0; i < operators.length; i++) {
            stakingProviders[i] = self.operatorToStakingProvider[operators[i]];
        }

        return stakingProviders;
    }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will need to do some diligence here and figure out where does the cost of gas come from. If it is real TokenStaking or something else. TokenStaking writes to the queue so the cost could increase by 1.2M for a whole group slashed but what we see is an increase by 3.28M for reportUnauthorizedSigning.

Copy link
Member Author

@nkuba nkuba Apr 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a group of 100 operators, the total cost of reportUnauthorizedSigning would be 5 726 857. It turns out that:

  • sortitionPool.getIDOperators costs 326 864
  • operatorToStakingProvider loop costs 249 402
  • tokenStaking.seize costs 4 858 014

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the TokenStaking perspective it's slashingQueue.push that produces such a cost burden. For tokenStaking.seize call mentioned above the slashingQueue.push execution consumes 4 546 619 out of the 4 858 014.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nkuba added 2 commits April 4, 2022 11:46
We no longer need this setting as there are no more matches in the
tests.
// unique addresses in staking for each operator.
accounts: { count: 10 + 5 * 64 },
tags: ["local"],
allowUnlimitedContractSize: true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only for RandomBeaconStub, right? It is quite dangerous because we may end up with non-deployable RandomBeacon and not even notice it. Would it be possible to branch-off from this PR, remove this line, and try to make tests passing by, for example, dividing RandomBeaconStub into several per-test stubs?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the RandomBeaconStub is problematic. I already tried to reduce the size of the stub in #2906. There is not much room for RandomBeacon to grow as it's 24.091 KB already.

As I mentioned in the commit 90e6594 we're protected by the hardhat-contract-sizer. Whenever we run yarn build the plugin will verify the size of the RandomBeacon.

Would it be possible to branch-off from this PR, remove this line, and try to make tests passing by, for example, dividing RandomBeaconStub into several per-test stubs?

If the contract sizer is not enough in your opinion, I can try slicing the contract.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try slicing and we'll see where we end up with. I am not a fan of stubs adding a lot of functionality because in the end, we do not know what we are testing - the final contract or stub. On the other hand, having just one stub could (unsure) be better for aggregating gas usage reports by hardhat plugin.

Copy link
Member Author

@nkuba nkuba Apr 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW hardhat-contract-sizer will fail contracts build in case of a too big contract. It means that CI will fail and PR won't be mergeable. See example PR #2912

nkuba added 5 commits April 4, 2022 15:33
For consistency I aliased BeaconInactivity as we do for other Beacon*
libraries.
Also I gathered aliased imports together to make it prettier.
Some adjustments to tests to make them even more fabulous! 🌟
To be more clear about accounts configuration for tests we defined
testConfig object that holds the config and those config are reused in
operators registration. Additionally we validate on hardhat test start
if the parameters are configured properly.
@pdyraga pdyraga merged commit d5f99af into main Apr 6, 2022
@pdyraga pdyraga deleted the random-beacon-t-staking-integration branch April 6, 2022 13:43
@pdyraga
Copy link
Member

pdyraga commented Apr 6, 2022

The problem of slashing gas costs mentioned in the PR description is addressed in threshold-network/solidity-contracts#87.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Integrate T staking contract with RandomBeacon

3 participants