From b8078bb673e89573a218d0bc4dbb6979675b2cc1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?=
Date: Sun, 24 May 2026 07:24:30 +0000
Subject: [PATCH 1/3] chore: extract v1 random beacon to keep-core-v1 repo
Move docs-v1/ and solidity-v1/ into a new dedicated repository
threshold-network/keep-core-v1 to reduce this repo's footprint and
remove dead-weight CI paths, CODEOWNERS noise, and pre-commit hooks
that target inert legacy code.
- Remove docs-v1/ and solidity-v1/ trees.
- Remove scripts/install-v1.sh (only set up v1 truffle migrations).
- Remove crytic-config.json (only pointed at solidity-v1).
- Preserve docs-v1/development/go-guidelines.adoc under
docs/development/ since it documents Go code that still lives here.
- Strip v1 entries from CODEOWNERS, .dockerignore, paths-ignore /
path-filter in client workflow, and v1-specific pre-commit hooks.
- Drop the v1 npm install from scripts/macos-setup.sh, keep the
generic npm install (v2 contracts still need it).
- Repoint narrative links in README.adoc, docs/retired-components.md,
docs/development/README.adoc and solidity/random-beacon/README.adoc
at the new keep-core-v1 repository.
The historical solc-input deployment artifacts under
solidity/random-beacon/deployments/ and solidity/ecdsa/deployments/
still reference 'solidity-v1' inside frozen compiler metadata; those
are immutable build artifacts and are intentionally left untouched.
Likewise, solidity/random-beacon/contracts/libraries/BytesLib.sol
keeps a permalink-by-commit-SHA pointer to the original v1 source in
keep-network/keep-core; that link remains valid.
---
.dockerignore | 1 -
.github/workflows/client.yml | 4 +-
.pre-commit-config.yaml | 18 -
CODEOWNERS | 33 -
README.adoc | 44 +-
crytic-config.json | 3 -
docs-v1/.gitignore | 9 -
docs-v1/Makefile | 27 -
docs-v1/README.adoc | 7 -
docs-v1/development-process.adoc | 151 -
docs-v1/development/README.adoc | 125 -
docs-v1/development/local-keep-network.adoc | 647 -
docs-v1/glossary.adoc | 62 -
docs-v1/img-src/libp2p-join.tikz | 23 -
docs-v1/img-src/relay-diagram.tikz | 55 -
.../relay-entry-request-processing.tikz | 28 -
docs-v1/img-src/relay-entry-verification.tikz | 20 -
docs-v1/img-src/relay-group-assignment.tikz | 17 -
.../img-src/relay-group-initialization.tikz | 36 -
docs-v1/img-src/relay-group-setup.tikz | 54 -
docs-v1/img-src/startup-diagram.tikz | 14 -
docs-v1/monitoring-and-alerting.adoc | 97 -
docs-v1/random-beacon/README.adoc | 30 -
docs-v1/random-beacon/alt_bn128.adoc | 48 -
docs-v1/random-beacon/authorizations.adoc | 197 -
docs-v1/random-beacon/beacon-pricing.py | 147 -
docs-v1/random-beacon/contract-structure.adoc | 112 -
docs-v1/random-beacon/delegation-notes.adoc | 544 -
docs-v1/random-beacon/dkg/alternative.adoc | 428 -
docs-v1/random-beacon/dkg/concepts.adoc | 50 -
docs-v1/random-beacon/dkg/dkg.py | 397 -
docs-v1/random-beacon/dkg/dkg_bls.py | 240 -
docs-v1/random-beacon/dkg/dkg_util.py | 235 -
docs-v1/random-beacon/dkg/index.adoc | 428 -
docs-v1/random-beacon/dkg/notes.adoc | 257 -
docs-v1/random-beacon/dkg/terms.adoc | 148 -
docs-v1/random-beacon/glossary.adoc | 62 -
.../random-beacon/group-expiration/index.adoc | 532 -
.../random-beacon/group-expiration/terms.adoc | 1 -
.../group-selection/general.adoc | 207 -
.../random-beacon/group-selection/index.adoc | 311 -
.../random-beacon/group-selection/terms.adoc | 1 -
docs-v1/random-beacon/group_selection.py | 242 -
docs-v1/random-beacon/incentives.adoc | 394 -
docs-v1/random-beacon/index.adoc | 172 -
docs-v1/random-beacon/misbehavior.adoc | 332 -
docs-v1/random-beacon/pricing.adoc | 341 -
docs-v1/random-beacon/signing/index.adoc | 114 -
docs-v1/random-beacon/signing/sign.py | 72 -
docs-v1/random-beacon/signing/terms.adoc | 1 -
docs-v1/random-beacon/slashing.adoc | 206 -
docs-v1/random-beacon/staking/index.adoc | 529 -
docs-v1/random-beacon/staking/notes.adoc | 350 -
docs-v1/random-beacon/terms.adoc | 153 -
docs-v1/random-beacon/upgrades.adoc | 81 -
docs-v1/relay-states.tex | 134 -
.../rfc-1-network-security-requirements.adoc | 217 -
.../rfc/rfc-11-upgrade-authorizations.adoc | 461 -
.../rfc/rfc-12-keep-network-interface.adoc | 194 -
docs-v1/rfc/rfc-13-continuous-delivery.adoc | 299 -
docs-v1/rfc/rfc-14-token-grants.adoc | 739 -
docs-v1/rfc/rfc-15-slashing.adoc | 447 -
docs-v1/rfc/rfc-16-pricing.adoc | 551 -
docs-v1/rfc/rfc-17-undelegation.adoc | 383 -
.../rfc/rfc-18-files/release-flow-chart.png | Bin 348256 -> 0 bytes
docs-v1/rfc/rfc-18-release-management.adoc | 490 -
...rfc-2-network-security-implementation.adoc | 197 -
.../rfc-3-stake-delegation-requirements.adoc | 362 -
.../rfc/rfc-4-secure-contract-upgrades.adoc | 89 -
.../rfc-5-stake-delegation-specification.adoc | 243 -
...roup-expiration-minimal-specification.adoc | 97 -
...rfc-7-dkg-voting-update-specification.adoc | 80 -
...8-beacon-signature-share-verification.adoc | 125 -
...rfc-9-upgradeable-contract-components.adoc | 405 -
docs-v1/rfc/rfc.adoc | 61 -
docs-v1/run-random-beacon.adoc | 563 -
docs-v1/scripts/generate-pngs.sh | 27 -
docs-v1/scripts/package-lock.json | 154 -
docs-v1/scripts/package.json | 6 -
docs-v1/scripts/yellowpaper-probabilities.js | 68 -
.../2020-11-11-retro-geth-hardfork.adoc | 125 -
.../tbtc-2020-09-15-to-2020-10-13.adoc | 330 -
docs/development/README.adoc | 2 +-
.../development/go-guidelines.adoc | 0
docs/retired-components.md | 17 +-
scripts/install-v1.sh | 85 -
scripts/macos-setup.sh | 3 +-
solidity-v1/.babelrc | 3 -
solidity-v1/.eslintrc | 15 -
solidity-v1/.soliumrc.json | 17 -
solidity-v1/Makefile | 16 -
solidity-v1/README.md | 7 -
solidity-v1/contracts/.gitignore | 1 -
.../contracts/AdaptiveStakingPolicy.sol | 98 -
solidity-v1/contracts/Authorizations.sol | 171 -
.../contracts/BeaconBackportRewards.sol | 148 -
solidity-v1/contracts/BeaconRewards.sol | 239 -
solidity-v1/contracts/Escrow.sol | 45 -
solidity-v1/contracts/GasPriceOracle.sol | 103 -
solidity-v1/contracts/GrantStakingPolicy.sol | 15 -
.../GuaranteedMinimumStakingPolicy.sol | 64 -
solidity-v1/contracts/IRandomBeacon.sol | 106 -
.../contracts/KeepRandomBeaconOperator.sol | 827 -
.../contracts/KeepRandomBeaconService.sol | 304 -
.../KeepRandomBeaconServiceImplV1.sol | 540 -
solidity-v1/contracts/KeepRegistry.sol | 235 -
solidity-v1/contracts/KeepToken.sol | 51 -
solidity-v1/contracts/ManagedGrant.sol | 192 -
solidity-v1/contracts/ManagedGrantFactory.sol | 172 -
solidity-v1/contracts/Migrations.sol | 23 -
.../contracts/PermissiveStakingPolicy.sol | 23 -
solidity-v1/contracts/PhasedEscrow.sol | 283 -
solidity-v1/contracts/Rewards.sol | 731 -
solidity-v1/contracts/StakeDelegatable.sol | 61 -
solidity-v1/contracts/StakingPortBacker.sol | 290 -
solidity-v1/contracts/TokenGrant.sol | 596 -
solidity-v1/contracts/TokenGrantStake.sol | 109 -
solidity-v1/contracts/TokenSender.sol | 10 -
solidity-v1/contracts/TokenStaking.sol | 702 -
.../contracts/cryptography/AltBn128.sol | 587 -
solidity-v1/contracts/cryptography/BLS.sol | 63 -
.../contracts/examples/CallbackContract.sol | 19 -
.../KeepRandomBeaconServiceUpgradeExample.sol | 56 -
solidity-v1/contracts/geyser/IStaking.sol | 47 -
.../contracts/geyser/KeepTokenGeyser.sol | 101 -
solidity-v1/contracts/geyser/KeepVault.sol | 39 -
solidity-v1/contracts/geyser/TokenGeyser.sol | 687 -
solidity-v1/contracts/geyser/TokenPool.sol | 46 -
.../contracts/libraries/RolesLookup.sol | 92 -
.../libraries/grant/UnlockingSchedule.sol | 29 -
.../operator/DKGResultVerification.sol | 118 -
.../libraries/operator/DelayFactor.sol | 50 -
.../libraries/operator/GroupSelection.sol | 400 -
.../contracts/libraries/operator/Groups.sol | 474 -
.../libraries/operator/Reimbursements.sol | 67 -
.../libraries/staking/GrantStaking.sol | 166 -
.../contracts/libraries/staking/LockUtils.sol | 85 -
.../contracts/libraries/staking/Locks.sol | 119 -
.../staking/MinimumStakeSchedule.sol | 28 -
.../contracts/libraries/staking/TopUps.sol | 150 -
.../KeepRandomBeaconOperatorStatistics.sol | 99 -
.../stubs/DelegatedAuthorityStub.sol | 21 -
.../contracts/stubs/EvilStakingPolicy.sol | 22 -
.../stubs/GasPriceOracleConsumerStub.sol | 17 -
.../contracts/stubs/GrantStakingStub.sol | 24 -
.../contracts/stubs/GroupsExpirationStub.sol | 44 -
.../contracts/stubs/GroupsSelectionStub.sol | 47 -
.../contracts/stubs/GroupsTerminationStub.sol | 29 -
...pRandomBeaconOperatorBeaconRewardsStub.sol | 45 -
.../KeepRandomBeaconOperatorCallbackStub.sol | 45 -
.../KeepRandomBeaconOperatorDKGResultStub.sol | 57 -
...RandomBeaconOperatorGroupSelectionStub.sol | 36 -
...RandomBeaconOperatorInitializationStub.sol | 34 -
...eepRandomBeaconOperatorMisbehaviorStub.sol | 43 -
...KeepRandomBeaconOperatorPricingDKGStub.sol | 53 -
...aconOperatorPricingRewardsWithdrawStub.sol | 46 -
.../KeepRandomBeaconOperatorPricingStub.sol | 57 -
.../KeepRandomBeaconOperatorRewardsStub.sol | 55 -
...RandomBeaconOperatorServicePricingStub.sol | 56 -
.../KeepRandomBeaconOperatorSlashingStub.sol | 32 -
.../stubs/KeepRandomBeaconOperatorStub.sol | 59 -
solidity-v1/contracts/stubs/LockStub.sol | 33 -
.../stubs/MinimumStakeScheduleStub.sol | 11 -
.../contracts/stubs/NewRewardsStub.sol | 17 -
.../contracts/stubs/OldTokenStaking.sol | 149 -
.../contracts/stubs/OperatorParamsStub.sol | 64 -
solidity-v1/contracts/stubs/RewardsStub.sol | 148 -
.../contracts/stubs/RolesLookupStub.sol | 56 -
solidity-v1/contracts/stubs/TestAltBn128.sol | 449 -
.../contracts/stubs/TestArrayUtils.sol | 114 -
solidity-v1/contracts/stubs/TestModUtils.sol | 298 -
.../stubs/TestPhasedEscrowBeneficiaries.sol | 55 -
solidity-v1/contracts/stubs/TestToken.sol | 15 -
.../stubs/TokenStakingSlashingStub.sol | 43 -
.../contracts/stubs/TokenStakingStub.sol | 32 -
.../token-distribution/TokenDistributor.sol | 258 -
.../contracts/utils/AddressArrayUtils.sol | 34 -
solidity-v1/contracts/utils/BytesLib.sol | 491 -
solidity-v1/contracts/utils/ModUtils.sol | 114 -
.../contracts/utils/OperatorParams.sol | 134 -
solidity-v1/contracts/utils/PercentUtils.sol | 20 -
.../contracts/utils/UintArrayUtils.sol | 21 -
solidity-v1/migrations/1_initial_migration.js | 5 -
solidity-v1/migrations/2_deploy_contracts.js | 184 -
solidity-v1/migrations/3_initialize.js | 51 -
solidity-v1/package-lock.json | 60646 ----------------
solidity-v1/package.json | 70 -
solidity-v1/requirements.txt | 1 -
solidity-v1/scripts/create-grants.js | 77 -
solidity-v1/scripts/delegate-tokens.js | 81 -
solidity-v1/scripts/etherscan-verify.sh | 37 -
solidity-v1/scripts/gas-used-test.js | 41 -
solidity-v1/scripts/generate-api-docs.js | 54 -
solidity-v1/scripts/genesis.js | 20 -
solidity-v1/scripts/keep-token-geyser-init.js | 58 -
solidity-v1/scripts/lcl-client-config.js | 87 -
solidity-v1/scripts/manage-stake.js | 176 -
solidity-v1/scripts/misbehaved-groups.js | 51 -
solidity-v1/scripts/pricing-test.js | 336 -
.../request-relay-entry-with-callback.js | 52 -
solidity-v1/scripts/request-relay-entry.js | 94 -
solidity-v1/scripts/rewards.js | 149 -
.../staking-port-backer-dapp-starter.js | 200 -
solidity-v1/scripts/unlock-eth-accounts.js | 32 -
solidity-v1/slither.config.json | 4 -
solidity-v1/tenderly.yaml | 7 -
solidity-v1/test-environment.config.js | 5 -
solidity-v1/test/RolesLookupTest.js | 486 -
solidity-v1/test/TestAltBn128.js | 136 -
solidity-v1/test/TestArrayUtils.js | 42 -
solidity-v1/test/TestBLS.js | 162 -
solidity-v1/test/TestEscrow.js | 181 -
solidity-v1/test/TestGasPriceOracle.js | 194 -
solidity-v1/test/TestKeepRegistry.js | 574 -
solidity-v1/test/TestModUtils.js | 46 -
solidity-v1/test/TestOperatorParams.js | 128 -
solidity-v1/test/TestPhasedEscrow.js | 1114 -
solidity-v1/test/TestToken.js | 47 -
.../test/geyser/TestKeepTokenGeyser.js | 427 -
solidity-v1/test/geyser/TestTokenGeyser.js | 140 -
solidity-v1/test/helpers/data.js | 52 -
solidity-v1/test/helpers/delegateStake.js | 71 -
solidity-v1/test/helpers/generateTickets.js | 22 -
solidity-v1/test/helpers/grantTokens.js | 65 -
solidity-v1/test/helpers/initContracts.js | 173 -
solidity-v1/test/helpers/numbers.js | 35 -
solidity-v1/test/helpers/packTicket.js | 17 -
solidity-v1/test/helpers/shuffle.js | 9 -
solidity-v1/test/helpers/signature.js | 19 -
solidity-v1/test/helpers/snapshot.js | 50 -
solidity-v1/test/helpers/stakeAndGenesis.js | 169 -
solidity-v1/test/helpers/stakeDelegate.js | 19 -
.../TestDkgMisbehavior.js | 237 -
.../TestGroupExpiration.js | 331 -
.../TestGroupSelection.js | 362 -
.../TestGroupTermination.js | 250 -
.../TestInitialization.js | 45 -
.../TestManageServiceContracts.js | 80 -
.../TestPricingRewards.js | 284 -
.../TestPricingRewardsWithdraw.js | 381 -
.../TestPublishDkgResult.js | 653 -
.../random_beacon_operator/TestRelayEntry.js | 99 -
.../TestRelayEntryTimeout.js | 251 -
.../random_beacon_operator/TestSlashing.js | 389 -
.../TestTicketsOrdering.js | 257 -
.../test/random_beacon_service/TestPricing.js | 256 -
.../random_beacon_service/TestPricingDkg.js | 131 -
.../random_beacon_service/TestPricingFees.js | 72 -
.../TestRelayRequestCallback.js | 891 -
.../TestSelectOperator.js | 157 -
.../test/random_beacon_service/TestUpgrade.js | 344 -
.../random_beacon_service/TestViaProxy.js | 235 -
.../test/rewards/TestBeaconBackportRewards.js | 169 -
solidity-v1/test/rewards/TestBeaconRewards.js | 408 -
.../test/rewards/TestRewardUpgrades.js | 294 -
solidity-v1/test/rewards/TestRewards.js | 586 -
solidity-v1/test/rewards/rewardsData.js | 61 -
.../TokenDistributorTest.js | 691 -
.../test/token-distribution/testData.json | 82 -
.../token_grant/TestManagedGrantFactory.js | 218 -
.../test/token_grant/TestStakingPolicy.js | 452 -
.../test/token_grant/TestTokenGrant.js | 241 -
.../token_grant/TestTokenGrantWithdraw.js | 169 -
.../token_stake/TestDelegatedAuthority.js | 371 -
.../test/token_stake/TestGrantStakingLib.js | 90 -
solidity-v1/test/token_stake/TestLockUtils.js | 94 -
.../test/token_stake/TestMinimumStake.js | 82 -
.../test/token_stake/TestPunishment.js | 285 -
.../test/token_stake/TestStakingPortBacker.js | 779 -
.../test/token_stake/TestTokenStake.js | 1075 -
.../test/token_stake/TestTokenStakeLock.js | 351 -
solidity-v1/truffle-config.js | 84 -
solidity/random-beacon/README.adoc | 2 +-
273 files changed, 35 insertions(+), 108038 deletions(-)
delete mode 100644 crytic-config.json
delete mode 100644 docs-v1/.gitignore
delete mode 100644 docs-v1/Makefile
delete mode 100644 docs-v1/README.adoc
delete mode 100644 docs-v1/development-process.adoc
delete mode 100644 docs-v1/development/README.adoc
delete mode 100644 docs-v1/development/local-keep-network.adoc
delete mode 100644 docs-v1/glossary.adoc
delete mode 100644 docs-v1/img-src/libp2p-join.tikz
delete mode 100644 docs-v1/img-src/relay-diagram.tikz
delete mode 100644 docs-v1/img-src/relay-entry-request-processing.tikz
delete mode 100644 docs-v1/img-src/relay-entry-verification.tikz
delete mode 100644 docs-v1/img-src/relay-group-assignment.tikz
delete mode 100644 docs-v1/img-src/relay-group-initialization.tikz
delete mode 100644 docs-v1/img-src/relay-group-setup.tikz
delete mode 100644 docs-v1/img-src/startup-diagram.tikz
delete mode 100644 docs-v1/monitoring-and-alerting.adoc
delete mode 100644 docs-v1/random-beacon/README.adoc
delete mode 100644 docs-v1/random-beacon/alt_bn128.adoc
delete mode 100644 docs-v1/random-beacon/authorizations.adoc
delete mode 100644 docs-v1/random-beacon/beacon-pricing.py
delete mode 100644 docs-v1/random-beacon/contract-structure.adoc
delete mode 100644 docs-v1/random-beacon/delegation-notes.adoc
delete mode 100644 docs-v1/random-beacon/dkg/alternative.adoc
delete mode 100644 docs-v1/random-beacon/dkg/concepts.adoc
delete mode 100644 docs-v1/random-beacon/dkg/dkg.py
delete mode 100644 docs-v1/random-beacon/dkg/dkg_bls.py
delete mode 100644 docs-v1/random-beacon/dkg/dkg_util.py
delete mode 100644 docs-v1/random-beacon/dkg/index.adoc
delete mode 100644 docs-v1/random-beacon/dkg/notes.adoc
delete mode 100644 docs-v1/random-beacon/dkg/terms.adoc
delete mode 100644 docs-v1/random-beacon/glossary.adoc
delete mode 100644 docs-v1/random-beacon/group-expiration/index.adoc
delete mode 100644 docs-v1/random-beacon/group-expiration/terms.adoc
delete mode 100644 docs-v1/random-beacon/group-selection/general.adoc
delete mode 100644 docs-v1/random-beacon/group-selection/index.adoc
delete mode 100644 docs-v1/random-beacon/group-selection/terms.adoc
delete mode 100644 docs-v1/random-beacon/group_selection.py
delete mode 100644 docs-v1/random-beacon/incentives.adoc
delete mode 100644 docs-v1/random-beacon/index.adoc
delete mode 100644 docs-v1/random-beacon/misbehavior.adoc
delete mode 100644 docs-v1/random-beacon/pricing.adoc
delete mode 100644 docs-v1/random-beacon/signing/index.adoc
delete mode 100644 docs-v1/random-beacon/signing/sign.py
delete mode 100644 docs-v1/random-beacon/signing/terms.adoc
delete mode 100644 docs-v1/random-beacon/slashing.adoc
delete mode 100644 docs-v1/random-beacon/staking/index.adoc
delete mode 100644 docs-v1/random-beacon/staking/notes.adoc
delete mode 100644 docs-v1/random-beacon/terms.adoc
delete mode 100644 docs-v1/random-beacon/upgrades.adoc
delete mode 100644 docs-v1/relay-states.tex
delete mode 100644 docs-v1/rfc/rfc-1-network-security-requirements.adoc
delete mode 100644 docs-v1/rfc/rfc-11-upgrade-authorizations.adoc
delete mode 100644 docs-v1/rfc/rfc-12-keep-network-interface.adoc
delete mode 100644 docs-v1/rfc/rfc-13-continuous-delivery.adoc
delete mode 100644 docs-v1/rfc/rfc-14-token-grants.adoc
delete mode 100644 docs-v1/rfc/rfc-15-slashing.adoc
delete mode 100644 docs-v1/rfc/rfc-16-pricing.adoc
delete mode 100644 docs-v1/rfc/rfc-17-undelegation.adoc
delete mode 100644 docs-v1/rfc/rfc-18-files/release-flow-chart.png
delete mode 100644 docs-v1/rfc/rfc-18-release-management.adoc
delete mode 100644 docs-v1/rfc/rfc-2-network-security-implementation.adoc
delete mode 100644 docs-v1/rfc/rfc-3-stake-delegation-requirements.adoc
delete mode 100644 docs-v1/rfc/rfc-4-secure-contract-upgrades.adoc
delete mode 100644 docs-v1/rfc/rfc-5-stake-delegation-specification.adoc
delete mode 100644 docs-v1/rfc/rfc-6-group-expiration-minimal-specification.adoc
delete mode 100644 docs-v1/rfc/rfc-7-dkg-voting-update-specification.adoc
delete mode 100644 docs-v1/rfc/rfc-8-beacon-signature-share-verification.adoc
delete mode 100644 docs-v1/rfc/rfc-9-upgradeable-contract-components.adoc
delete mode 100644 docs-v1/rfc/rfc.adoc
delete mode 100644 docs-v1/run-random-beacon.adoc
delete mode 100644 docs-v1/scripts/generate-pngs.sh
delete mode 100644 docs-v1/scripts/package-lock.json
delete mode 100644 docs-v1/scripts/package.json
delete mode 100644 docs-v1/scripts/yellowpaper-probabilities.js
delete mode 100644 docs-v1/status-reports/2020-11-11-retro-geth-hardfork.adoc
delete mode 100644 docs-v1/status-reports/tbtc-2020-09-15-to-2020-10-13.adoc
rename {docs-v1 => docs}/development/go-guidelines.adoc (100%)
delete mode 100755 scripts/install-v1.sh
delete mode 100644 solidity-v1/.babelrc
delete mode 100644 solidity-v1/.eslintrc
delete mode 100644 solidity-v1/.soliumrc.json
delete mode 100644 solidity-v1/Makefile
delete mode 100644 solidity-v1/README.md
delete mode 100644 solidity-v1/contracts/.gitignore
delete mode 100644 solidity-v1/contracts/AdaptiveStakingPolicy.sol
delete mode 100644 solidity-v1/contracts/Authorizations.sol
delete mode 100644 solidity-v1/contracts/BeaconBackportRewards.sol
delete mode 100644 solidity-v1/contracts/BeaconRewards.sol
delete mode 100644 solidity-v1/contracts/Escrow.sol
delete mode 100644 solidity-v1/contracts/GasPriceOracle.sol
delete mode 100644 solidity-v1/contracts/GrantStakingPolicy.sol
delete mode 100644 solidity-v1/contracts/GuaranteedMinimumStakingPolicy.sol
delete mode 100644 solidity-v1/contracts/IRandomBeacon.sol
delete mode 100644 solidity-v1/contracts/KeepRandomBeaconOperator.sol
delete mode 100644 solidity-v1/contracts/KeepRandomBeaconService.sol
delete mode 100644 solidity-v1/contracts/KeepRandomBeaconServiceImplV1.sol
delete mode 100644 solidity-v1/contracts/KeepRegistry.sol
delete mode 100644 solidity-v1/contracts/KeepToken.sol
delete mode 100644 solidity-v1/contracts/ManagedGrant.sol
delete mode 100644 solidity-v1/contracts/ManagedGrantFactory.sol
delete mode 100644 solidity-v1/contracts/Migrations.sol
delete mode 100644 solidity-v1/contracts/PermissiveStakingPolicy.sol
delete mode 100644 solidity-v1/contracts/PhasedEscrow.sol
delete mode 100644 solidity-v1/contracts/Rewards.sol
delete mode 100644 solidity-v1/contracts/StakeDelegatable.sol
delete mode 100644 solidity-v1/contracts/StakingPortBacker.sol
delete mode 100644 solidity-v1/contracts/TokenGrant.sol
delete mode 100644 solidity-v1/contracts/TokenGrantStake.sol
delete mode 100644 solidity-v1/contracts/TokenSender.sol
delete mode 100644 solidity-v1/contracts/TokenStaking.sol
delete mode 100644 solidity-v1/contracts/cryptography/AltBn128.sol
delete mode 100644 solidity-v1/contracts/cryptography/BLS.sol
delete mode 100644 solidity-v1/contracts/examples/CallbackContract.sol
delete mode 100644 solidity-v1/contracts/examples/KeepRandomBeaconServiceUpgradeExample.sol
delete mode 100644 solidity-v1/contracts/geyser/IStaking.sol
delete mode 100644 solidity-v1/contracts/geyser/KeepTokenGeyser.sol
delete mode 100644 solidity-v1/contracts/geyser/KeepVault.sol
delete mode 100644 solidity-v1/contracts/geyser/TokenGeyser.sol
delete mode 100644 solidity-v1/contracts/geyser/TokenPool.sol
delete mode 100644 solidity-v1/contracts/libraries/RolesLookup.sol
delete mode 100644 solidity-v1/contracts/libraries/grant/UnlockingSchedule.sol
delete mode 100644 solidity-v1/contracts/libraries/operator/DKGResultVerification.sol
delete mode 100644 solidity-v1/contracts/libraries/operator/DelayFactor.sol
delete mode 100644 solidity-v1/contracts/libraries/operator/GroupSelection.sol
delete mode 100644 solidity-v1/contracts/libraries/operator/Groups.sol
delete mode 100644 solidity-v1/contracts/libraries/operator/Reimbursements.sol
delete mode 100644 solidity-v1/contracts/libraries/staking/GrantStaking.sol
delete mode 100644 solidity-v1/contracts/libraries/staking/LockUtils.sol
delete mode 100644 solidity-v1/contracts/libraries/staking/Locks.sol
delete mode 100644 solidity-v1/contracts/libraries/staking/MinimumStakeSchedule.sol
delete mode 100644 solidity-v1/contracts/libraries/staking/TopUps.sol
delete mode 100644 solidity-v1/contracts/statistics/KeepRandomBeaconOperatorStatistics.sol
delete mode 100644 solidity-v1/contracts/stubs/DelegatedAuthorityStub.sol
delete mode 100644 solidity-v1/contracts/stubs/EvilStakingPolicy.sol
delete mode 100644 solidity-v1/contracts/stubs/GasPriceOracleConsumerStub.sol
delete mode 100644 solidity-v1/contracts/stubs/GrantStakingStub.sol
delete mode 100644 solidity-v1/contracts/stubs/GroupsExpirationStub.sol
delete mode 100644 solidity-v1/contracts/stubs/GroupsSelectionStub.sol
delete mode 100644 solidity-v1/contracts/stubs/GroupsTerminationStub.sol
delete mode 100644 solidity-v1/contracts/stubs/KeepRandomBeaconOperatorBeaconRewardsStub.sol
delete mode 100644 solidity-v1/contracts/stubs/KeepRandomBeaconOperatorCallbackStub.sol
delete mode 100644 solidity-v1/contracts/stubs/KeepRandomBeaconOperatorDKGResultStub.sol
delete mode 100644 solidity-v1/contracts/stubs/KeepRandomBeaconOperatorGroupSelectionStub.sol
delete mode 100644 solidity-v1/contracts/stubs/KeepRandomBeaconOperatorInitializationStub.sol
delete mode 100644 solidity-v1/contracts/stubs/KeepRandomBeaconOperatorMisbehaviorStub.sol
delete mode 100644 solidity-v1/contracts/stubs/KeepRandomBeaconOperatorPricingDKGStub.sol
delete mode 100644 solidity-v1/contracts/stubs/KeepRandomBeaconOperatorPricingRewardsWithdrawStub.sol
delete mode 100644 solidity-v1/contracts/stubs/KeepRandomBeaconOperatorPricingStub.sol
delete mode 100644 solidity-v1/contracts/stubs/KeepRandomBeaconOperatorRewardsStub.sol
delete mode 100644 solidity-v1/contracts/stubs/KeepRandomBeaconOperatorServicePricingStub.sol
delete mode 100644 solidity-v1/contracts/stubs/KeepRandomBeaconOperatorSlashingStub.sol
delete mode 100644 solidity-v1/contracts/stubs/KeepRandomBeaconOperatorStub.sol
delete mode 100644 solidity-v1/contracts/stubs/LockStub.sol
delete mode 100644 solidity-v1/contracts/stubs/MinimumStakeScheduleStub.sol
delete mode 100644 solidity-v1/contracts/stubs/NewRewardsStub.sol
delete mode 100644 solidity-v1/contracts/stubs/OldTokenStaking.sol
delete mode 100644 solidity-v1/contracts/stubs/OperatorParamsStub.sol
delete mode 100644 solidity-v1/contracts/stubs/RewardsStub.sol
delete mode 100644 solidity-v1/contracts/stubs/RolesLookupStub.sol
delete mode 100644 solidity-v1/contracts/stubs/TestAltBn128.sol
delete mode 100644 solidity-v1/contracts/stubs/TestArrayUtils.sol
delete mode 100644 solidity-v1/contracts/stubs/TestModUtils.sol
delete mode 100644 solidity-v1/contracts/stubs/TestPhasedEscrowBeneficiaries.sol
delete mode 100644 solidity-v1/contracts/stubs/TestToken.sol
delete mode 100644 solidity-v1/contracts/stubs/TokenStakingSlashingStub.sol
delete mode 100644 solidity-v1/contracts/stubs/TokenStakingStub.sol
delete mode 100644 solidity-v1/contracts/token-distribution/TokenDistributor.sol
delete mode 100644 solidity-v1/contracts/utils/AddressArrayUtils.sol
delete mode 100644 solidity-v1/contracts/utils/BytesLib.sol
delete mode 100644 solidity-v1/contracts/utils/ModUtils.sol
delete mode 100644 solidity-v1/contracts/utils/OperatorParams.sol
delete mode 100644 solidity-v1/contracts/utils/PercentUtils.sol
delete mode 100644 solidity-v1/contracts/utils/UintArrayUtils.sol
delete mode 100644 solidity-v1/migrations/1_initial_migration.js
delete mode 100644 solidity-v1/migrations/2_deploy_contracts.js
delete mode 100644 solidity-v1/migrations/3_initialize.js
delete mode 100644 solidity-v1/package-lock.json
delete mode 100644 solidity-v1/package.json
delete mode 100644 solidity-v1/requirements.txt
delete mode 100644 solidity-v1/scripts/create-grants.js
delete mode 100644 solidity-v1/scripts/delegate-tokens.js
delete mode 100755 solidity-v1/scripts/etherscan-verify.sh
delete mode 100644 solidity-v1/scripts/gas-used-test.js
delete mode 100644 solidity-v1/scripts/generate-api-docs.js
delete mode 100644 solidity-v1/scripts/genesis.js
delete mode 100644 solidity-v1/scripts/keep-token-geyser-init.js
delete mode 100644 solidity-v1/scripts/lcl-client-config.js
delete mode 100644 solidity-v1/scripts/manage-stake.js
delete mode 100644 solidity-v1/scripts/misbehaved-groups.js
delete mode 100644 solidity-v1/scripts/pricing-test.js
delete mode 100644 solidity-v1/scripts/request-relay-entry-with-callback.js
delete mode 100644 solidity-v1/scripts/request-relay-entry.js
delete mode 100644 solidity-v1/scripts/rewards.js
delete mode 100644 solidity-v1/scripts/staking-port-backer-dapp-starter.js
delete mode 100644 solidity-v1/scripts/unlock-eth-accounts.js
delete mode 100644 solidity-v1/slither.config.json
delete mode 100644 solidity-v1/tenderly.yaml
delete mode 100644 solidity-v1/test-environment.config.js
delete mode 100644 solidity-v1/test/RolesLookupTest.js
delete mode 100644 solidity-v1/test/TestAltBn128.js
delete mode 100644 solidity-v1/test/TestArrayUtils.js
delete mode 100644 solidity-v1/test/TestBLS.js
delete mode 100644 solidity-v1/test/TestEscrow.js
delete mode 100644 solidity-v1/test/TestGasPriceOracle.js
delete mode 100644 solidity-v1/test/TestKeepRegistry.js
delete mode 100644 solidity-v1/test/TestModUtils.js
delete mode 100644 solidity-v1/test/TestOperatorParams.js
delete mode 100644 solidity-v1/test/TestPhasedEscrow.js
delete mode 100644 solidity-v1/test/TestToken.js
delete mode 100644 solidity-v1/test/geyser/TestKeepTokenGeyser.js
delete mode 100644 solidity-v1/test/geyser/TestTokenGeyser.js
delete mode 100644 solidity-v1/test/helpers/data.js
delete mode 100644 solidity-v1/test/helpers/delegateStake.js
delete mode 100644 solidity-v1/test/helpers/generateTickets.js
delete mode 100644 solidity-v1/test/helpers/grantTokens.js
delete mode 100644 solidity-v1/test/helpers/initContracts.js
delete mode 100644 solidity-v1/test/helpers/numbers.js
delete mode 100644 solidity-v1/test/helpers/packTicket.js
delete mode 100644 solidity-v1/test/helpers/shuffle.js
delete mode 100644 solidity-v1/test/helpers/signature.js
delete mode 100644 solidity-v1/test/helpers/snapshot.js
delete mode 100644 solidity-v1/test/helpers/stakeAndGenesis.js
delete mode 100644 solidity-v1/test/helpers/stakeDelegate.js
delete mode 100644 solidity-v1/test/random_beacon_operator/TestDkgMisbehavior.js
delete mode 100644 solidity-v1/test/random_beacon_operator/TestGroupExpiration.js
delete mode 100644 solidity-v1/test/random_beacon_operator/TestGroupSelection.js
delete mode 100644 solidity-v1/test/random_beacon_operator/TestGroupTermination.js
delete mode 100644 solidity-v1/test/random_beacon_operator/TestInitialization.js
delete mode 100644 solidity-v1/test/random_beacon_operator/TestManageServiceContracts.js
delete mode 100644 solidity-v1/test/random_beacon_operator/TestPricingRewards.js
delete mode 100644 solidity-v1/test/random_beacon_operator/TestPricingRewardsWithdraw.js
delete mode 100644 solidity-v1/test/random_beacon_operator/TestPublishDkgResult.js
delete mode 100644 solidity-v1/test/random_beacon_operator/TestRelayEntry.js
delete mode 100644 solidity-v1/test/random_beacon_operator/TestRelayEntryTimeout.js
delete mode 100644 solidity-v1/test/random_beacon_operator/TestSlashing.js
delete mode 100644 solidity-v1/test/random_beacon_operator/TestTicketsOrdering.js
delete mode 100644 solidity-v1/test/random_beacon_service/TestPricing.js
delete mode 100644 solidity-v1/test/random_beacon_service/TestPricingDkg.js
delete mode 100644 solidity-v1/test/random_beacon_service/TestPricingFees.js
delete mode 100644 solidity-v1/test/random_beacon_service/TestRelayRequestCallback.js
delete mode 100644 solidity-v1/test/random_beacon_service/TestSelectOperator.js
delete mode 100644 solidity-v1/test/random_beacon_service/TestUpgrade.js
delete mode 100644 solidity-v1/test/random_beacon_service/TestViaProxy.js
delete mode 100644 solidity-v1/test/rewards/TestBeaconBackportRewards.js
delete mode 100644 solidity-v1/test/rewards/TestBeaconRewards.js
delete mode 100644 solidity-v1/test/rewards/TestRewardUpgrades.js
delete mode 100644 solidity-v1/test/rewards/TestRewards.js
delete mode 100644 solidity-v1/test/rewards/rewardsData.js
delete mode 100644 solidity-v1/test/token-distribution/TokenDistributorTest.js
delete mode 100644 solidity-v1/test/token-distribution/testData.json
delete mode 100644 solidity-v1/test/token_grant/TestManagedGrantFactory.js
delete mode 100644 solidity-v1/test/token_grant/TestStakingPolicy.js
delete mode 100644 solidity-v1/test/token_grant/TestTokenGrant.js
delete mode 100644 solidity-v1/test/token_grant/TestTokenGrantWithdraw.js
delete mode 100644 solidity-v1/test/token_stake/TestDelegatedAuthority.js
delete mode 100644 solidity-v1/test/token_stake/TestGrantStakingLib.js
delete mode 100644 solidity-v1/test/token_stake/TestLockUtils.js
delete mode 100644 solidity-v1/test/token_stake/TestMinimumStake.js
delete mode 100644 solidity-v1/test/token_stake/TestPunishment.js
delete mode 100644 solidity-v1/test/token_stake/TestStakingPortBacker.js
delete mode 100644 solidity-v1/test/token_stake/TestTokenStake.js
delete mode 100644 solidity-v1/test/token_stake/TestTokenStakeLock.js
delete mode 100644 solidity-v1/truffle-config.js
diff --git a/.dockerignore b/.dockerignore
index 9c48e7b076..6f381299e4 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -17,7 +17,6 @@ Dockerfile
**/node_modules/*
# Solidity stuff.
-solidity-v1/
solidity/
# Token Stakedrop stuff.
diff --git a/.github/workflows/client.yml b/.github/workflows/client.yml
index 7daced9b82..468686798a 100644
--- a/.github/workflows/client.yml
+++ b/.github/workflows/client.yml
@@ -7,12 +7,10 @@ on:
branches:
- main
paths-ignore:
- - "docs-v1/**"
- "docs/**"
- "infrastructure/**"
- "scripts/**"
- "solidity/**"
- - "solidity-v1/**"
pull_request:
workflow_dispatch:
inputs:
@@ -45,7 +43,7 @@ jobs:
with:
filters: |
path-filter:
- - './!((docs-v1|docs|infrastructure|scripts|solidity|solidity-v1)/**)'
+ - './!((docs|infrastructure|scripts|solidity)/**)'
electrum-integration-detect-changes:
runs-on: ubuntu-latest
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index e0de398304..344fb1e331 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -30,24 +30,6 @@ repos:
files: '\.(json|yaml)$'
language: script
description: "Checks JSON/YAML code according to the package's linter configuration"
- - id: lint-js-v1
- name: 'lint solidity-v1 js'
- entry: /usr/bin/env bash -c "cd solidity-v1 && npm run lint:js"
- files: 'solidity-v1\/.*\.js$'
- language: script
- description: "Checks JS code according to the package's linter configuration"
- - id: lint-sol-v1
- name: 'lint solidity-v1 sol'
- entry: /usr/bin/env bash -c "cd solidity-v1 && npm run lint:sol"
- files: 'solidity-v1\/.*\.sol$'
- language: script
- description: "Checks solidity code according to the package's linter configuration"
- - id: format-dashboard
- name: 'format dashboard'
- entry: /usr/bin/env bash -c "cd solidity-v1/dashboard && npm run format"
- files: 'solidity-v1/dashboard/'
- language: script
- description: "Checks dashboard code according to the package's formatting configuration"
- id: lint-faucet-js
name: 'lint faucet js'
entry: /usr/bin/env bash -c "cd infrastructure/gcp/keep-test/google-functions/keep-faucet && npm run lint:js"
diff --git a/CODEOWNERS b/CODEOWNERS
index 899eb9e154..3e0d8a9a6d 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -1,35 +1,2 @@
-/solidity-v1/contracts/KeepToken.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/TokenGrant.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/TokenGrantStake.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/TokenStaking.sol @Shadowfiend @pdyraga @nkuba
-/solidity-v1/contracts/StakeDelegatable.sol @Shadowfiend @pdyraga @nkuba
-/solidity-v1/contracts/ManagedGrant.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/ManagedGrantFactory.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/AdaptiveStakingPolicy.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/MinimumStakingPolicy.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/GuaranteedMinimumStakingPolicy.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/PermissiveStakingPolicy.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/KeepRegistry.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/Escrow.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/KeepRandomBeaconOperator.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/KeepRandomBeaconService.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/KeepRandomBeaconServiceImplV1.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/statistics/KeepRandomBeaconOperatorStatistics.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/libraries/grant/UnlockingSchedule.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/libraries/operator/DelayFactor.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/libraries/operator/DKGResultVerification.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/libraries/operator/Groups.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/libraries/operator/GroupSelection.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/libraries/operator/Reimbursements.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/libraries/staking/GrantStaking.sol @Shadowfiend @pdyraga @nkuba
-/solidity-v1/contracts/libraries/staking/LockUtils.sol @Shadowfiend @pdyraga @nkuba
-/solidity-v1/contracts/libraries/staking/Locks.sol @Shadowfiend @pdyraga @nkuba
-/solidity-v1/contracts/libraries/staking/MinimumStakeSchedule.sol @Shadowfiend @pdyraga @nkuba
-/solidity-v1/contracts/utils/AddressArrayUtils.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/utils/BytesLib.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/utils/OperatorParams.sol @Shadowfiend @pdyraga @nkuba
-/solidity-v1/contracts/utils/PercentUtils.sol @Shadowfiend @pdyraga
-/solidity-v1/contracts/utils/UIntArrayUtils.sol @Shadowfiend @pdyraga
-/solidity-v1/package.json @Shadowfiend @pdyraga
/solidity/ecdsa/contracts/ @pdyraga @nkuba @lukasz-zimnoch @dimpar @tomaszslabon
/solidity/random-beacon/contracts/ @pdyraga @nkuba @lukasz-zimnoch @dimpar @tomaszslabon
diff --git a/README.adoc b/README.adoc
index 5553f08c7b..f38d0c320a 100644
--- a/README.adoc
+++ b/README.adoc
@@ -45,10 +45,11 @@ https://github.com/keep-network/keep-core/issues[is appreciated!]
=== Moving to a new random beacon
-The legacy core contracts of the random beacon are moved to the
-link:solidity-v1/[`solidity-v1/`] directory which can be referred as "v1". The
-newest "v2" random beacon contracts can be found in
-link:solidity/random-beacon/[`solidity/random-beacon`] directory. The full
+The legacy "v1" random beacon contracts have been moved out of this repository
+and now live in
+https://github.com/threshold-network/keep-core-v1[`threshold-network/keep-core-v1`]
+(under its `solidity/` directory). The current "v2" random beacon contracts can
+be found in link:solidity/random-beacon/[`solidity/random-beacon`]. The full
specification of the "v2" random beacon is written in
link:/docs/rfc/rfc-19-random-beacon-v2.adoc[`rfc-19-random-beacon-v2.adoc`].
Retired KEEP-era packages and operational tooling are listed in
@@ -59,12 +60,11 @@ link:docs/retired-components.md[`docs/retired-components.md`].
dApp developers will be most interested in the smart contracts exposing Keep's
on-chain facilities.
-The core contracts can be found in the link:solidity-v1/[`solidity-v1/`]
-directory. They can be used to request
-link:solidity-v1/contracts/IRandomBeacon.sol[miner-resistant random numbers], as
-well as creating and managing keeps. To generate new ECDSA key material and
-request signatures, the contracts can be found in
-link:solidity/ecdsa/contracts/[`solidity/ecdsa/contracts/`].
+The legacy v1 core contracts (miner-resistant random numbers, keep creation and
+management) live in
+https://github.com/threshold-network/keep-core-v1[`threshold-network/keep-core-v1`].
+To generate new ECDSA key material and request signatures, the contracts can be
+found in link:solidity/ecdsa/contracts/[`solidity/ecdsa/contracts/`].
=== Client Developers
@@ -85,35 +85,33 @@ keep-core/
solidity/ <1>
ecdsa/
random-beacon/
- solidity-v1/ <2>
- cmd/ <3>
- pkg/ <4>
+ cmd/ <2>
+ pkg/ <3>
net/
- net.go, *.go <5>
+ net.go, *.go <4>
libp2p/
chain/
- chain.go, *.go <5>
+ chain.go, *.go <4>
ethereum/
gen/
- gen.go <6>
+ gen.go <5>
relay/
relay.go, *.go
```
<1> Core contracts of the Keep contracts. Random beacon contracts are stored
under `/solidity/random-beacon` whereas ECDSA under `/solidity/ecdsa`.
-<2> Legacy core contracts of the random beacon (v1). While the Keep network only
- uses Solidity at the moment, the directory structure allows for other
- contract languages.
-<3> Keep client subcommands are implemented here, though they should be minimal
+ Legacy v1 contracts live in the separate
+ https://github.com/threshold-network/keep-core-v1[`keep-core-v1`] repo.
+<2> Keep client subcommands are implemented here, though they should be minimal
and deal solely with user interaction. The meat of the commands should exist
in a package fit for the appropriate purpose.
-<4> All additional packages live in `pkg/`.
-<5> The high-level interfaces for a package `mypackage` live in `mypackage.go`.
+<3> All additional packages live in `pkg/`.
+<4> The high-level interfaces for a package `mypackage` live in `mypackage.go`.
`net` and `chain` are interface packages that expose a common interface to
network and blockchain layers. Their subpackages provide particular
implementations of these common interfaces. Only `cmd/` and the main package
should interact with the implementations directly.
-<6> When a package requires generated code, it should have a subpackage named
+<5> When a package requires generated code, it should have a subpackage named
`gen/`. This subpackage should contain a single file, `gen.go`, with a `//
go:generate` annotation to trigger appropriate code generation. All code
generation is done with a single invocation of `go generate` at build time.
diff --git a/crytic-config.json b/crytic-config.json
deleted file mode 100644
index 34cb256d2e..0000000000
--- a/crytic-config.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "cwd": "solidity-v1"
-}
diff --git a/docs-v1/.gitignore b/docs-v1/.gitignore
deleted file mode 100644
index e1074103a6..0000000000
--- a/docs-v1/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-*.aux
-*.log
-*.gz
-*.pdf
-*.fls
-*.out
-*.fdb_latexmk
-img/generated
-*.html
\ No newline at end of file
diff --git a/docs-v1/Makefile b/docs-v1/Makefile
deleted file mode 100644
index 6fc8ab59e0..0000000000
--- a/docs-v1/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-SHELL = /bin/bash
-
-generated_img_dir=img/generated
-
-tikz_files := $(wildcard img-src/*.tikz)
-
-tikz_pngs := $(foreach file, $(tikz_files), $(generated_img_dir)/$(notdir $(basename $(file))).png)
-
-.PHONY: clean docs pngs
-
-clean:
- shopt -s nullglob; \
- rm -f *.aux *.log *.gz *.pdf *.ps *.dvi *.out *.fls *.fdb_latexmk \
- img-src/*.aux img-src/*.log img-src/*.gz img-src/*.pdf img-src/*.ps \
- img-src/*.dvi img-src/*.out img-src/*.fls img-src/*.fdb_latexmk; \
- rm -rf img/generated
-
-relay-states.pdf: relay-states.tex
- pdflatex -halt-on-error relay-states.tex; \
- pdflatex -halt-on-error relay-states.tex
-
-$(tikz_pngs): img/generated/%.png: img-src/%.tikz
- bash scripts/generate-pngs.sh /tmp/png-generate img/generated $< $(basename $(*F))
-
-pngs: $(tikz_pngs)
-
-docs: relay-states.pdf $(tikz_pngs)
\ No newline at end of file
diff --git a/docs-v1/README.adoc b/docs-v1/README.adoc
deleted file mode 100644
index c107dba8d1..0000000000
--- a/docs-v1/README.adoc
+++ /dev/null
@@ -1,7 +0,0 @@
-= Keep Network v1 Documentation (Legacy)
-
-WARNING: This directory contains historical specifications and design documents
-for the *v1 random beacon*. They are preserved for reference only and do not
-reflect the current protocol.
-
-For current documentation, see the link:../docs/[`docs/`] directory.
diff --git a/docs-v1/development-process.adoc b/docs-v1/development-process.adoc
deleted file mode 100644
index cd508147de..0000000000
--- a/docs-v1/development-process.adoc
+++ /dev/null
@@ -1,151 +0,0 @@
-:toc: macro
-
-= Keep Development Process
-
-:icons: font
-:numbered:
-toc::[]
-
-In this document, we describe the Keep development process from an
-organizational perspective. We identify events and artifacts allowing for
-a transparent, adaptable and predictable development process.
-
-== Sprint
-
-Sprint is a time-box of one week during which a product increment is created.
-Product increment is a sum of all items completed within the sprint by the team.
-Each sprint has a goal of what is to be built, and a plan guiding the building
-process. A new sprint starts immediately after the conclusion of the previous
-sprint. The scope of a sprint is identified during the sprint planning meeting.
-Individual team members may have a specialized area of focus but they all
-cooperate on the implementation of sprint items and accountability for reaching
-the sprint goal belongs to the team as a whole.
-
-== Milestone
-
-Milestone is a box of items identifying releasable product increment with no
-more than one-month horizon of development effort. Milestone contains items from
-one or more sprints. Each milestone has an expected delivery date assigned,
-evaluated from estimates.
-
-== Sprint planning meeting
-
-The sprint planning meeting is a time-boxed event of one hour happening at the
-beginning of each new sprint where all dsciplines, such as growth, design and
-engineering identify work planned for the next sprint.
-
-Planning meeting consists of two parts: retrospective and new sprint planning.
-
-=== Retrospective
-
-Retrospective part is time-boxed to a maximum of 15 minutes. During this part,
-the Keep team inspects how the previous sprint went. Every member has a chance
-to tell what in their opinion went particularly well and what could be improved.
-
-=== New sprint planning
-
-The input to new sprint planning is product backlog, latest product increment,
-and any other prior planning work performed by specialized disciplines
-independently. The entire team collaborates on understanding the work that is
-going to be performed in the next sprint. Sprint planning should result in
-crafting a sprint goal which is an objective to be met by the implementation of
-items in the sprint.
-
-== Engineering planning meeting
-
-Before each new sprint planning, engineering team meets to collaborate on
-estimating, breaking down, and discussing all the technical issues related to
-backlog product items. Engineering team consist of all disciplines involved in
-the software development process: research, devops, and developers.
-
-Everyone is welcome to join the meeting but only purely technical subjects
-are discussed.
-
-Engineering planning meeting is time-boxed to one hour.
-
-At the beginning of meeting, there is a 10-minutes time-box for technical
-retrospective.
-
-Before the meeting, tech lead sends to all participants a list of items from the
-top of the backlog that are going to be discussed during the meeting.
-Items should be presented in a clear way allowing the development team to
-understand all the details to the level needed. Each development team member
-should invest some time in preparation for the meeting by thoroughly reviewing
-selected items and writing down questions.
-
-Estimates are provided by team members and should include enough development
-effort to meet the definition of done for the given item. At the end of the
-planning meeting, each individual item should have at least one team member
-assigned, but accountability for completion of the items in the sprint belongs
-to the whole team.
-
-By the end of the engineering planning meeting, each team member should be able
-to explain how they intend to work to implement the selected items. Individual
-tasks may be clarified and re-organized later as more is learned.
-
-== Daily Standup
-
-The goal of the daily standup is to optimize team performance and collaboration.
-The target audience of daily standup is not primarily the manager; instead, it
-is a way for the other team members to track sprint progress, identify
-impediments, and synchronize about required development work.
-
-Everyone should answer three questions for a daily standup:
-
-1. What did I do since the last daily standup?
-2. What will I do today to progress work towards achieving the sprint goal?
-3. Are there any blockers that prevent me from progressing the work?
-
-Development team members should be specific and provide enough details so that
-other team members know the current status, and if they work on the same
-item, what should they do next and in what order.
-
-=== Example of a good daily standup
-
-*Yesterday*
-
-* DKG result conflict resolution phase
-** Opened PR with a stub interface for the on-chain part: ,
-** Did initial work on off-chain voting event handling code, just local chain
-stub implementation, no PR yet.
-
-*Today*
-
-* Continuing work on the DKG result conflict resolution phase
-** I received a review on my stub on-chain interface, want to address all
-comments. Should be ready today for another review round,
-** I want to finish Ethereum off-chain voting event handling code and open
-PR today. It will contain local chain stub implementation as well.
-Should be ready for review at the end of the day.
-
-*Blockers*
-
-* I do not understand how conflict resolution phase votes are summarized, need
-to talk with someone about it.
-
-
-== Definition of Done
-
-When sprint item is described as “Done” everyone must share the same
-understanding of what “Done” means. For a milestone item to be considered as
-“Done”, the following requirements must be met:
-
-* The implemented code has been reviewed and approved by at least one other development team member
-* Code merged to `main` branch
-* The feature described by the item works as expected
-* The code is implemented according to the guidelines
-* No technical debt other than agreed in the item’s description
-* Tests implemented and passing
-* Item does not break other existing functionalities
-
-== Work tracking
-
-We use GitHub to capture backlog items, plan development team work and track
-progress on sprint and milestone.
-
-Each item is a separate GitHub issue. Each sprint has a separate board
-under the Keep Network project. Each milestone has a separate milestone board
-under Keep Network project. All backlog items are ordered under a separate
-backlog project in the Keep Network project.
-
-All pull requests implementing sprint items reference appropriate issue.
diff --git a/docs-v1/development/README.adoc b/docs-v1/development/README.adoc
deleted file mode 100644
index 27e80f4624..0000000000
--- a/docs-v1/development/README.adoc
+++ /dev/null
@@ -1,125 +0,0 @@
-:toc: macro
-
-= Keep developer documentation
-
-toc::[]
-
-== Getting Set Up
-
-If you're on macOS, install Homebrew and run `scripts/macos-setup.sh`. Note
-that if you don't have Homebrew or you're not on macOS, the below information
-details what you'll need. The script additionally sets up pre-commit hooks.
-
-== Building
-
-Currently the easiest way to build is using the `Dockerfile` at the root of the
-repository. A simple `docker build` should get you a functioning container.
-
-If you want to build natively, there are a few prereqs you'll need to go through.
-In particular, you'll need the
-https://developers.google.com/protocol-buffers/docs/downloads[protobuf
-compiler]. You'll also need to install the `protoc-gen-go` toolchain,
-which you can install using `go get`:
-
-```
-go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
-```
-
-Run `+go generate ./.../+` from `keep-core` and if everything is fine, start the
-Keep client with `go run main.go`.
-
-== <>
-
-For development purposes, it is convenient to set up local Ethereum client with
-a group of connected peers. A note-taken walkthrough covers the entire process
-including setting up local Ethereum client, deploying Keep contracts and
-configuring Keep peers.
-
-== Quick installation
-
-To quickly install and start a client use the following scripts.
-
-=== Install script
-
-The `+install.sh+` script will:
-
-* migrate contracts
-* update client config files
-* build client
-
-The script will ask you for the password to previously created ethereum
-accounts.
-
-To start the installation execute:
-
-....
-./scripts/install.sh
-....
-
-=== Starting a client
-
-To start a client execute:
-
-....
-./scripts/start.sh
-....
-
-The `+start.sh+` script will ask you to:
-
-* provide ethereum password
-* provide path to `keep-core` config files directory
-* select a config `.toml` file for your client
-
-== Development Guidelines
-
-There are two primary languages in the Keep code right now:
-
-Go::
- Go code largely adheres to community practices where they have been decided.
- Divergences and additional tidbits are listed in the link:go-guidelines.adoc[Go
- Guidelines] document.
-
-Solidity::
- Solidity code generally adheres to the
- https://solidity.readthedocs.io/en/latest/style-guide.html[Solidity style guide].
- Contracts and their functions are documented using
- https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format[the
- Ethereum Natural Specification Format] (NatSpec).
-
-== Relay States
-
-There is a set of threshold relay state diagrams auto-generated from this
-repo's `docs` available at https://docs.keep.network/relay-states.pdf. The
-images in the diagram, whose sources are at `img-src/*.tikz`, are also
-available at `+https://docs.keep.network/img/generated/*.png+` (the filenames
-are identical to their TikZ sources, with a `.png` suffix instead of
-`.tikz`). These URLs are for the `main` version of the repo; non-`main`
-branches are instead published to `+https://docs.keep.network//+`.
-
-== Common problems
-
-- Please avoid using `~` when defining `$GOBIN` location and use `$HOME` instead.
- We've been observing https://github.com/google/protobuf/issues/3355[some issues]
- with locating `protoc-gen-go` when running `go generate` and `$GOBIN`
- contained `~`.
-
-- For Mojave, if you have a problem with missing include or missing library and
- you are sure that you have installed xcode with `xcode-select --install`. Then
- install the following package:
- `/Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg`
-
-== Working with Solidity contracts
-
-The fastest and easiest way to have local Ethereum testent is to use Ganache app.
-https://truffleframework.com/ganache/
-
-You can also use a demo script to help you deploy contracts to your local testnet
-and to have demo balances (token, staking and token grants) allocated between first
-two accounts.
-
-Go to `solidity` directory and run:
-
-```
-npm install
-npm run demo
-```
diff --git a/docs-v1/development/local-keep-network.adoc b/docs-v1/development/local-keep-network.adoc
deleted file mode 100644
index a37ace3ade..0000000000
--- a/docs-v1/development/local-keep-network.adoc
+++ /dev/null
@@ -1,647 +0,0 @@
-:toc: macro
-
-= Setting up local Keep network for development purposes
-
-toc::[]
-
-== Pre-requirements
-* Installed `geth` Ethereum client
-* Installed `truffle` framework
-
-The `scripts/macos-setup.sh` installs all required packages. Please consult
-<> for details.
-
-[#set-up-local-ethereum]
-== Setting up local Ethereum client
-
-Create directories for Ethereum client data:
-
-```
-$ mkdir ~/ethereum
-$ mkdir ~/ethereum/data
-$ mkdir ~/ethereum/data/keystore
-```
-
-[#ethereum-accounts]
-=== Generate ethereum accounts
-
-Create a new account for Ethereum client, set the password to just `password`.
-For a real environment, please use some better password.
-```
-$ geth account new --keystore ~/ethereum/data/keystore
-
-INFO [10-31|14:28:07.264] Maximum peer count ETH=25 LES=0 total=25
-Your new account is locked with a password. Please give a password. Do not forget this password.
-Passphrase:
-Repeat passphrase:
-Address: {3e208f39da1bc335464f40d85546ad6a1b66a9a4}
-```
-
-Create a new account for each Keep peer individually. Peer's network identifier
-is derived from the account's address and all messages from the peer are signed
-with the private key belonging to the account. In this document, we will create
-5 accounts for 5 peers. For simplicity, please set the password to just
-`password`. For a real environment, please use some better password.
-```
-$ geth account new --keystore ~/ethereum/data/keystore
-
-INFO [10-31|14:31:18.980] Maximum peer count ETH=25 LES=0 total=25
-Your new account is locked with a password. Please give a password. Do not forget this password.
-Passphrase:
-Repeat passphrase:
-Address: {a232599810ecc03816adf607272705b71ff271ac}
-
-$ geth account new --keystore ~/ethereum/data/keystore
-
-INFO [10-31|14:31:38.690] Maximum peer count ETH=25 LES=0 total=25
-Your new account is locked with a password. Please give a password. Do not forget this password.
-Passphrase:
-Repeat passphrase:
-Address: {b7314de01d5f3188c7df0a9e95f3477bcaae2120}
-
-$ geth account new --keystore ~/ethereum/data/keystore
-
-INFO [10-31|14:34:46.260] Maximum peer count ETH=25 LES=0 total=25
-Your new account is locked with a password. Please give a password. Do not forget this password.
-Passphrase:
-Repeat passphrase:
-Address: {5ef1e10dd1830af50924db623c7a9d90bf8a71be}
-
-$ geth account new --keystore ~/ethereum/data/keystore
-
-INFO [10-31|14:35:08.025] Maximum peer count ETH=25 LES=0 total=25
-Your new account is locked with a password. Please give a password. Do not forget this password.
-Passphrase:
-Repeat passphrase:
-Address: {64c20c1ae603c30553de4ea5dd10cc1760b956be}
-
-$ geth account new --keystore ~/ethereum/data/keystore
-INFO [10-31|14:35:27.173] Maximum peer count ETH=25 LES=0 total=25
-Your new account is locked with a password. Please give a password. Do not forget this password.
-Passphrase:
-Repeat passphrase:
-Address: {c4cba981a8edb64276f71a49f9392bad7a726417}
-```
-
-Check if accounts have been created correctly and `geth` can recognize them:
-```
-$ geth account list --keystore ~/ethereum/data/keystore/
-
-Account #0: {3e208f39da1bc335464f40d85546ad6a1b66a9a4} keystore:///Users/piotr/ethereum/data/keystore/UTC--2018-10-31T13-28-13.525596422Z--3e208f39da1bc335464f40d85546ad6a1b66a9a4
-Account #1: {a232599810ecc03816adf607272705b71ff271ac} keystore:///Users/piotr/ethereum/data/keystore/UTC--2018-10-31T13-31-24.735759049Z--a232599810ecc03816adf607272705b71ff271ac
-Account #2: {b7314de01d5f3188c7df0a9e95f3477bcaae2120} keystore:///Users/piotr/ethereum/data/keystore/UTC--2018-10-31T13-31-43.391759751Z--b7314de01d5f3188c7df0a9e95f3477bcaae2120
-Account #3: {5ef1e10dd1830af50924db623c7a9d90bf8a71be} keystore:///Users/piotr/ethereum/data/keystore/UTC--2018-10-31T13-34-52.920270040Z--5ef1e10dd1830af50924db623c7a9d90bf8a71be
-Account #4: {64c20c1ae603c30553de4ea5dd10cc1760b956be} keystore:///Users/piotr/ethereum/data/keystore/UTC--2018-10-31T13-35-12.560028755Z--64c20c1ae603c30553de4ea5dd10cc1760b956be
-Account #5: {c4cba981a8edb64276f71a49f9392bad7a726417} keystore:///Users/piotr/ethereum/data/keystore/UTC--2018-10-31T13-35-31.551964909Z--c4cba981a8edb64276f71a49f9392bad7a726417
-```
-
-=== Initialize chain
-
-Initialize your local Ethereum node from `genesis.json` file. This allows to
-issue some tokens to the accounts we just created. We assign tokens to all
-addresses. The account under alloc is the address of the account prepended with
-`0x`.
-
-```
-{
- "config": {
- "chainId": 1101,
- "eip150Block": 0,
- "eip155Block": 0,
- "eip158Block": 0,
- "byzantiumBlock": 0,
- "homesteadBlock": 0,
- "constantinopleBlock": 0,
- "petersburgBlock": 0,
- "daoForkBlock": 0,
- "istanbulBlock": 0,
- "daoForkSupport": true
- },
- "difficulty": "0x20",
- "gasLimit": "0x7A1200",
- "alloc": {
- "0x3e208f39da1bc335464f40d85546ad6a1b66a9a4": { "balance": "1000000000000000000000000000000000000000000000000000000" },
- "0xa232599810ecc03816adf607272705b71ff271ac": { "balance": "1000000000000000000000000000000000000000000000000000000" },
- "0xb7314de01d5f3188c7df0a9e95f3477bcaae2120": { "balance": "1000000000000000000000000000000000000000000000000000000" },
- "0x5ef1e10dd1830af50924db623c7a9d90bf8a71be": { "balance": "1000000000000000000000000000000000000000000000000000000" },
- "0x64c20c1ae603c30553de4ea5dd10cc1760b956be": { "balance": "1000000000000000000000000000000000000000000000000000000" },
- "0xc4cba981a8edb64276f71a49f9392bad7a726417": { "balance": "1000000000000000000000000000000000000000000000000000000" }
- }
-}
-
-```
-
-Save the path to your data directory and `geth` client's account in
-environment variables:
-```
-$ export GETH_DATA_DIR=/Users/piotr/ethereum/data/
-$ export GETH_ETHEREUM_ACCOUNT=0x3e208f39da1bc335464f40d85546ad6a1b66a9a4
-```
-
-```
-$ geth --datadir=$GETH_DATA_DIR init genesis.json
-
-INFO [10-31|15:55:25.811] Maximum peer count ETH=25 LES=0 total=25
-INFO [10-31|15:55:25.823] Allocated cache and file handles database=/Users/piotr/ethereum/data/geth/chaindata cache=16 handles=16
-INFO [10-31|15:55:25.825] Writing custom genesis block
-INFO [10-31|15:55:25.825] Persisted trie from memory database nodes=8 size=1.30kB time=77.501µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
-INFO [10-31|15:55:25.826] Successfully wrote genesis state database=chaindata hash=d15d63…61dab6
-INFO [10-31|15:55:25.826] Allocated cache and file handles database=/Users/piotr/ethereum/data/geth/lightchaindata cache=16 handles=16
-INFO [10-31|15:55:25.827] Writing custom genesis block
-INFO [10-31|15:55:25.827] Persisted trie from memory database nodes=8 size=1.30kB time=57.219µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
-INFO [10-31|15:55:25.846] Successfully wrote genesis state database=lightchaindata hash=d15d63…61dab6
-```
-
-=== Run ethereum client
-
-Start Ethereum client locally using client's wallet address.
-
-```
-$ geth --port 3000 --networkid 1101 --identity "somerandomidentity" \
- --ws --wsaddr "127.0.0.1" --wsport "8546" --wsorigins "*" \
- --rpc --rpcport "8545" --rpcaddr "127.0.0.1" --rpccorsdomain "" \
- --rpcapi "db,ssh,miner,admin,eth,net,web3,personal" \
- --wsapi "db,ssh,miner,admin,eth,net,web3,personal" \
- --datadir=$GETH_DATA_DIR --syncmode "fast" \
- --miner.etherbase=$GETH_ETHEREUM_ACCOUNT --mine --miner.threads=1 \
- --allow-insecure-unlock
-
-INFO [10-31|15:02:22.113] Maximum peer count ETH=25 LES=0 total=25
-INFO [10-31|15:02:22.128] Starting peer-to-peer node instance=Geth/somerandomidentity/v1.8.14-stable/darwin-amd64/go1.10.3
-INFO [10-31|15:02:22.128] Allocated cache and file handles database=/Users/piotr/ethereum/data/geth/chaindata cache=768 handles=1024
-INFO [10-31|15:02:22.140] Initialised chain configuration config="{ChainID: 1101 Homestead: 0 DAO: DAOSupport: false EIP150: 0 EIP155: 0 EIP158: 0 Byzantium: 0 Constantinople: Engine: unknown}"
-INFO [10-31|15:02:22.141] Disk storage enabled for ethash caches dir=/Users/piotr/ethereum/data/geth/ethash count=3
-INFO [10-31|15:02:22.141] Disk storage enabled for ethash DAGs dir=/Users/piotr/.ethash count=2
-INFO [10-31|15:02:22.141] Initialising Ethereum protocol versions="[63 62]" network=1101
-INFO [10-31|15:02:22.142] Loaded most recent local header number=0 hash=840a3c…be07a4 td=32
-INFO [10-31|15:02:22.142] Loaded most recent local full block number=0 hash=840a3c…be07a4 td=32
-INFO [10-31|15:02:22.142] Loaded most recent local fast block number=0 hash=840a3c…be07a4 td=32
-INFO [10-31|15:02:22.143] Regenerated local transaction journal transactions=0 accounts=0
-INFO [10-31|15:02:22.145] Starting P2P networking
-INFO [10-31|15:02:24.256] UDP listener up self=enode://ef6ad0b1527093a1d3794acc16f3a914816006b1725ce47c5d0fb082f458cb8636c722c6173563f034e0e6ab74fb5230f343755334f1d3db487c744c058b4133@[::]:3000
-INFO [10-31|15:02:24.257] RLPx listener up self=enode://ef6ad0b1527093a1d3794acc16f3a914816006b1725ce47c5d0fb082f458cb8636c722c6173563f034e0e6ab74fb5230f343755334f1d3db487c744c058b4133@[::]:3000
-INFO [10-31|15:02:24.264] IPC endpoint opened url=/Users/piotr/ethereum/data/geth.ipc
-INFO [10-31|15:02:24.265] HTTP endpoint opened url=http://127.0.0.1:8545 cors= vhosts=localhost
-INFO [10-31|15:02:24.265] WebSocket endpoint opened url=ws://127.0.0.1:8546
-INFO [10-31|15:02:24.265] Transaction pool price threshold updated price=18000000000
-INFO [10-31|15:02:24.266] Commit new mining work number=1 uncles=0 txs=0 gas=0 fees=0 elapsed=388.897µs
-INFO [10-31|15:02:25.650] Generating DAG in progress epoch=0 percentage=0 elapsed=786.175ms
-INFO [10-31|15:02:26.422] Generating DAG in progress epoch=0 percentage=1 elapsed=1.558s
-INFO [10-31|15:02:27.199] Generating DAG in progress epoch=0 percentage=2 elapsed=2.335s
-
-(...)
-
-INFO [10-31|15:03:46.999] Generating DAG in progress epoch=0 percentage=97 elapsed=1m22.134s
-INFO [10-31|15:03:47.641] Generating DAG in progress epoch=0 percentage=98 elapsed=1m22.777s
-INFO [10-31|15:03:48.684] Generating DAG in progress epoch=0 percentage=99 elapsed=1m23.820s
-INFO [10-31|15:03:48.687] Generated ethash verification cache epoch=0 elapsed=1m23.822s
-INFO [10-31|15:03:49.846] Successfully sealed new block number=1 hash=927e38…9579e6 elapsed=1m25.580s
-INFO [10-31|15:03:49.852] 🔨 mined potential block number=1 hash=927e38…9579e6
-
-(...)
-```
-
-[#quick-installation]
-== Quick installation
-
-To quickly install and start a single client use the installation script.
-
-=== Prerequisites
-To run the script some manual preparation is needed:
-
-- <>,
-- <> for the single client (default name: `config.toml`).
-
-=== Install script
-The `install.sh` script will:
-
-- run <>,
-- run <>,
-- update <>
-- <>.
-
-The script will ask you for password to <>
-ethereum accounts and the client config file path.
-
-To start the installation execute:
-```
-./scripts/install.sh
-```
-
-=== Start client
-
-To start the client execute:
-```
-./scripts/start.sh
-```
-
-=== Run genesis entry request
-
-For the network to be fully functional you need to initialize the
-<>.
-
-[#contracts-deployment]
-== Keep contracts deployment
-
-Before we deploy Keep contracts to the local Ethereum network or stake Keep
-tokens, it is required to unlock addresses that will be used by Keep clients.
-We also unlock the account that will be used by Ethereum client since it will
-be used later to set up staking contract.
-
-```
-$ geth attach http://127.0.0.1:8545
-Welcome to the Geth JavaScript console!
-
-instance: Geth/somerandomidentity/v1.8.14-stable/darwin-amd64/go1.10.3
-coinbase: 0x3e208f39da1bc335464f40d85546ad6a1b66a9a4
-at block: 87 (Wed, 31 Oct 2018 15:06:39 CET)
- datadir: /Users/piotr/ethereum/data
- modules: admin:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 web3:1.0
-
-> personal.unlockAccount("0x3e208f39da1bc335464f40d85546ad6a1b66a9a4", "password", 150000);
-true
-> personal.unlockAccount("0xa232599810ecc03816adf607272705b71ff271ac", "password", 150000);
-true
-> personal.unlockAccount("0xb7314de01d5f3188c7df0a9e95f3477bcaae2120", "password", 150000);
-true
-> personal.unlockAccount("0x5ef1e10dd1830af50924db623c7a9d90bf8a71be", "password", 150000);
-true
-> personal.unlockAccount("0x64c20c1ae603c30553de4ea5dd10cc1760b956be", "password", 150000);
-true
-> personal.unlockAccount("0xc4cba981a8edb64276f71a49f9392bad7a726417", "password", 150000);
-true
-> exit
-```
-In several versions of geth (1.9.0 and above) you might encounter an error while executing account
-unlock commands described above.
-If you get `Account unlock with HTTP access is forbidden` you should run
-Ethereum client (described in the previous section) with param:
-`--allow-insecure-unlock`
-
-We also need to create a new network entry in `keep-core/solidity-v1/truffle-config.js`
-pointing to our local node and its account. This account will pay gas for Keep
-contract deployment.
-
-```
-local: {
- host: "localhost",
- port: 8545,
- network_id: "*",
- from: "0x3e208f39da1bc335464f40d85546ad6a1b66a9a4"
-},
-```
-
-Having done all those steps we can finally run a migration and deploy our
-contracts. Please save the output of as we will need to use some of the
-outputted contract addresses in the Keep peer configuration later.
-
-```
-$ cd keep-core/solidity-v1
-$ truffle migrate --reset --network local
-
-Using network 'local'.
-
-Running migration: 1_initial_migration.js
- Replacing Migrations...
- ... 0x38580e8248c8687a3a93e69a6a81687467efded85a3267b82ada3e7cc4f0a7a4
- Migrations: 0x7dd3bb48298b28444dc573e17c239d462600a802
-Saving successful migration to network...
- ... 0x4244901d95e662bff04dec6335e8c35163d12b9f9ca12fc2fe29a000c188c816
-Saving artifacts...
-Running migration: 2_deploy_contracts.js
- Running step...
- Replacing ModUtils...
- ... 0x55babc411b1d34279f5f93d81c629b8ff0d99966f397a6516b90a9bf26468e88
- ModUtils: 0x31f0535aec74aa862030bbc1bfe954d9e6cf7269
- Linking ModUtils to AltBn128
- Replacing AltBn128...
- ... 0x345a9de3bdbd476c1af75e11d4c2f2741d378f62fc31d7d149fb03accc41d59b
- AltBn128: 0x632988bc199f504cd57f9953f1896db1d5aa530e
- Replacing KeepToken...
- ... 0x2e1472bcf86de889e451828de94a3f6b673304767e49f050989d2bfcfba739ce
- KeepToken: 0xcb6a6a58f0badc45827d4bb221f5387f70ea6184
- Replacing TokenStaking...
- ... 0x61af5445af82db5b8da75a8e8fcd272c7c2a542a81b372662cde9b98d37a0cb0
- TokenStaking: 0xce812232c495262ff1423fa68b237177eda3af4c
- Replacing TokenGrant...
- ... 0xf3d4a78110ddd2003bd4c47bb59a0165e8468b3f38777131731d0829a5a3cfbf
- TokenGrant: 0x24e006907b85482b86c335c0c8e15c9ca49e6800
- Replacing KeepRandomBeaconServiceImplV1...
- ... 0x03a560288292005f2181fe561461aa70b521741349641c31525f64c1482caf25
- KeepRandomBeaconServiceImplV1: 0x3179d9c794e597d6316736189bf040b74a2f1dd7
- Replacing KeepRandomBeaconService...
- ... 0x9facb5fe566862e67e50d6ad0fc622f717ee5cb795c7044ba9ad2ff32f9faa70
- KeepRandomBeaconService: 0x15045ff30d6327345cc052cc4b8c28dbe974a74b
- Replacing KeepRandomBeaconOperator...
- ... 0x9e49a94de6dfbc6496c89bb3edff8201ad407ba906893029185f72be2c4e9528
- KeepRandomBeaconOperator: 0x9da7876f5404dde662bf5cbc6ca1462e777571ff
-Saving successful migration to network...
- ... 0xcb9a9ab4d9a0c153a7a24786d4aa1b61feb2b0278fd6fa2d91222e7324cce187
-Saving artifacts...
-```
-
-[#token-staking]
-== Keep token staking
-
-Each Keep peer needs to have a minimum number of KEEP tokens staked under its
-account. The `delegate-tokens.js` script transfers KEEP tokens and stake them for all
-addresses available.
-
-```
-$ truffle exec ./scripts/delegte-tokens.js --network local
-
-Using network 'local'.
-
-successfully staked KEEP tokens for account 0x3e208f39da1bc335464f40d85546ad6a1b66a9a4
-successfully staked KEEP tokens for account 0xa232599810ecc03816adf607272705b71ff271ac
-successfully staked KEEP tokens for account 0xb7314de01d5f3188c7df0a9e95f3477bcaae2120
-successfully staked KEEP tokens for account 0x5ef1e10dd1830af50924db623c7a9d90bf8a71be
-successfully staked KEEP tokens for account 0x64c20c1ae603c30553de4ea5dd10cc1760b956be
-successfully staked KEEP tokens for account 0xc4cba981a8edb64276f71a49f9392bad7a726417
-```
-
-== Setting up local Keep peers
-
-[#client-config-file]
-=== Prepare configuration file
-
-For each Keep peer we need to create a separate configuration file. We need at
-least one bootstrap peer in the network. Other peers are not required.
-Here, we will create one bootstrap peer and 4 other peers pointing to it.
-
-Let's create a configuration for the bootstrap peer first:
-```
-$ cp config.toml.SAMPLE config.local.1.toml
-```
-
-Next, edit `config.local.1.toml` and update `[ethereum.account]` section to
-point to the second <> (the first
-one is used by Ethereum client):
-```toml
-[ethereum.account]
- Address = "0x3e208f39da1bc335464f40d85546ad6a1b66a9a4"
- KeyFile = "/Users/piotr/ethereum/data/keystore/UTC--2018-10-31T13-28-13.525596422Z--3e208f39da1bc335464f40d85546ad6a1b66a9a4"
-```
-
-[#client-contracts-config]
-Update `[ethereum.ContractAddresses]` section to point to the previously
-*deployed contract* instances.
-
-NOTE: Updating contracts addresses is not required when running <>
-script.
-
-Please use addresses of `KeepRandomBeaconOperator`, `KeepRandomBeaconService` and
-`TokenStaking` contracts:
-
-```toml
-[ethereum.ContractAddresses]
- KeepRandomBeaconService = "0x15045ff30d6327345cc052cc4b8c28dbe974a74b"
- KeepRandomBeaconOperator = "0xdff3075ca23fe28697d5c4f171cf04abd79bd837"
- TokenStaking = "0xDfc7251170abd753342B585Adcd8BCEE48aDb379"
-```
-
-In the `config.local.1.toml` enable *network settings* for bootstrap peer:
-```toml
-[LibP2P]
- Port = 3919
-```
-
-And set a *storage directory* for the bootstrap peer:
-```toml
-[Storage]
- DataDir = "/Users/username/.keep/keep-core/storage/client-1"
-```
-This directory must be created before peer start.
-
-Next, create *configuration files for other peers*:
-```
-$ cp config.local.1.toml config.local.2.toml
-$ cp config.local.1.toml config.local.3.toml
-$ cp config.local.1.toml config.local.4.toml
-$ cp config.local.1.toml config.local.5.toml
-```
-
-NOTE: Configuration of other peers will <>
-after running the bootstrap peer.
-
-[#build-client]
-=== Build client
-
-Build the `keep-core` executable:
-```
-go generate ./...
-go build -a -o keep-core .
-```
-
-=== Start bootstrap peer
-
-Start the bootstrap peer:
-```
-$ LOG_LEVEL="info" KEEP_ETHEREUM_PASSWORD="password" ./keep-core --config config.local.1.toml start
-------------------------------------------------------------------------------------------------
-| Port: 3919 |
-| IPs : /ip6/::1/tcp/3919/ipfs/16Uiu2HAkvcmFM53nzHN4dAB4sfemFAu86ytA8wJveKQqYsHvfsca |
-| /ip4/192.168.1.103/tcp/3919/ipfs/16Uiu2HAkvcmFM53nzHN4dAB4sfemFAu86ytA8wJveKQqYsHvfsca |
-| /ip4/127.0.0.1/tcp/3919/ipfs/16Uiu2HAkvcmFM53nzHN4dAB4sfemFAu86ytA8wJveKQqYsHvfsca |
-------------------------------------------------------------------------------------------------
-```
-
-[#update-peers-config]
-==== Update other peers configuration
-
-The next thing we need to do is to alter configuration file of each peer.
-Please modify `Port` number so that it is unique for each
-peer and update the address of the bootstrap peer. We also need to update
-ethereum account and key file so that each Keep client uses a different account.
-
-In `config.local.2.toml`:
-```toml
-[LibP2P]
- Peers = ["/ip4/127.0.0.1/tcp/3919/ipfs/16Uiu2HAkvcmFM53nzHN4dAB4sfemFAu86ytA8wJveKQqYsHvfsca"]
- Port = 3920
-```
-```toml
-[ethereum.account]
- Address = "0xb7314de01d5f3188c7df0a9e95f3477bcaae2120"
- KeyFile = "/Users/piotr/ethereum/data/keystore/UTC--2018-10-31T13-31-43.391759751Z--b7314de01d5f3188c7df0a9e95f3477bcaae2120"
-```
-```toml
-[Storage]
- DataDir = "/Users/username/.keep/keep-core/storage/client-2"
-```
-
-In `config.local.3.toml`:
-```toml
-[LibP2P]
- Peers = ["/ip4/127.0.0.1/tcp/3919/ipfs/16Uiu2HAkvcmFM53nzHN4dAB4sfemFAu86ytA8wJveKQqYsHvfsca"]
- Port = 3921
-```
-```toml
-[ethereum.account]
- Address = "0x5ef1e10dd1830af50924db623c7a9d90bf8a71be"
- KeyFile = "/Users/piotr/ethereum/data/keystore/UTC--2018-10-31T13-34-52.920270040Z--5ef1e10dd1830af50924db623c7a9d90bf8a71be"
-```
-```toml
-[Storage]
- DataDir = "/Users/username/.keep/keep-core/storage/client-3"
-```
-
-In `config.local.4.toml`:
-```toml
-[LibP2P]
- Peers = ["/ip4/127.0.0.1/tcp/3919/ipfs/16Uiu2HAkvcmFM53nzHN4dAB4sfemFAu86ytA8wJveKQqYsHvfsca"]
- Port = 3922
-```
-```toml
-[ethereum.account]
- Address = "0x64c20c1ae603c30553de4ea5dd10cc1760b956be"
- KeyFile = "/Users/piotr/ethereum/data/keystore/UTC--2018-10-31T13-35-12.560028755Z--64c20c1ae603c30553de4ea5dd10cc1760b956be"
-```
-```toml
-[Storage]
- DataDir = "/Users/username/.keep/keep-core/storage/client-4"
-```
-
-In `config.local.5.toml`:
-```toml
-[LibP2P]
- Peers = ["/ip4/127.0.0.1/tcp/3919/ipfs/16Uiu2HAkvcmFM53nzHN4dAB4sfemFAu86ytA8wJveKQqYsHvfsca"]
- Port = 3923
-```
-```toml
-[ethereum.account]
- Address = "0xc4cba981a8edb64276f71a49f9392bad7a726417"
- KeyFile = "/Users/piotr/ethereum/data/keystore/UTC--2018-10-31T13-35-31.551964909Z--c4cba981a8edb64276f71a49f9392bad7a726417"
-```
-```toml
-[Storage]
- DataDir = "/Users/username/.keep/keep-core/storage/client-5"
-```
-
-==== Start other peers
-
-Finally, we can start each instance:
-```
-$ LOG_LEVEL="info" KEEP_ETHEREUM_PASSWORD="password" ./keep-core --config config.local.2.toml start
-------------------------------------------------------------------------------------------------
-| Port: 3920 |
-| IPs : /ip4/127.0.0.1/tcp/3919/ipfs/16Uiu2HAmGsfKJaP4UGoGWYV6nxY8RPhVoHxT9rUQbPsxFedMHzEr |
-| /ip6/::1/tcp/3919/ipfs/16Uiu2HAmGsfKJaP4UGoGWYV6nxY8RPhVoHxT9rUQbPsxFedMHzEr |
-| /ip4/192.168.1.103/tcp/3919/ipfs/16Uiu2HAmGsfKJaP4UGoGWYV6nxY8RPhVoHxT9rUQbPsxFedMHzEr |
-------------------------------------------------------------------------------------------------
-```
-
-```
-$ LOG_LEVEL="info" KEEP_ETHEREUM_PASSWORD="password" ./keep-core --config config.local.3.toml start
-------------------------------------------------------------------------------------------------
-| Port: 3921 |
-| IPs : /ip4/127.0.0.1/tcp/3919/ipfs/16Uiu2HAmAeFbeTZstFhAiEL8jGQiNR9sygKstrhpG4F2wKmt1784 |
-| /ip6/::1/tcp/3919/ipfs/16Uiu2HAmAeFbeTZstFhAiEL8jGQiNR9sygKstrhpG4F2wKmt1784 |
-| /ip4/192.168.1.103/tcp/3919/ipfs/16Uiu2HAmAeFbeTZstFhAiEL8jGQiNR9sygKstrhpG4F2wKmt1784 |
-------------------------------------------------------------------------------------------------
-```
-
-```
-$ LOG_LEVEL="info" KEEP_ETHEREUM_PASSWORD="password" ./keep-core --config config.local.4.toml start
-------------------------------------------------------------------------------------------------
-| Port: 3922 |
-| IPs : /ip4/127.0.0.1/tcp/3919/ipfs/16Uiu2HAmQcPbBVftPR8SKctpG9ToDmu7kLpaKPUc3AreEwzWbuyb |
-| /ip6/::1/tcp/3919/ipfs/16Uiu2HAmQcPbBVftPR8SKctpG9ToDmu7kLpaKPUc3AreEwzWbuyb |
-| /ip4/192.168.1.103/tcp/3919/ipfs/16Uiu2HAmQcPbBVftPR8SKctpG9ToDmu7kLpaKPUc3AreEwzWbuyb |
-------------------------------------------------------------------------------------------------
-```
-
-```
-$ LOG_LEVEL="info" KEEP_ETHEREUM_PASSWORD="password" ./keep-core --config config.local.5.toml start
-------------------------------------------------------------------------------------------------
-| Port: 3923 |
-| IPs : /ip4/127.0.0.1/tcp/3919/ipfs/16Uiu2HAm7wzWEs3fUbA9rgzKRP82Zhtnq2CxZZdXPMrJJgNNra1p |
-| /ip6/::1/tcp/3919/ipfs/16Uiu2HAm7wzWEs3fUbA9rgzKRP82Zhtnq2CxZZdXPMrJJgNNra1p |
-| /ip4/192.168.1.103/tcp/3919/ipfs/16Uiu2HAm7wzWEs3fUbA9rgzKRP82Zhtnq2CxZZdXPMrJJgNNra1p |
-------------------------------------------------------------------------------------------------
-```
-
-[#genesis-entry]
-== Genesis entry
-
-In order to trigger creation of the first group genesis entry must be submitted. The script includes
-the required DKG fee.
-```
-$ truffle exec ./scripts/genesis.js --network local
-
-Using network 'development'.
-
-Genesis entry successfully submitted.
-```
-
-
-== Request relay entry
-
-Once the first group is created we can request relay entry with the following script:
-```
-$ truffle exec ./scripts/request-relay-entry.js --network local
-
-Using network 'development'.
-
-Successfully requested relay entry with RequestId = 7
-
----Transaction Summary---
-From:0x23ba4cf58947d4eebd3b3aedcec28bec364b6727
-To:0x017a532a3bbb538753e84ae59d5131b0dfb7d2df
-BlockNumber:42
-TotalGas:106480
-TransactionHash:0x50dccd40f7f3f67e79598edff614bc250568127a97c0dab1a8011bf3c9cb9776
---------------------------
-
-```
-
-
-== Request relay entry with a callback
-
-If you want your contract to be called on a successful entry please use the script below in the following format:
-```
-truffle exec ./scripts/request-relay-entry-with-callback.js yourContractAddress "callbackMethodName" payment
-```
-
-Example usage:
-
-```
-$ truffle exec ./scripts/request-relay-entry-with-callback.js 0x230cD94D6a4d3923da88d38b362337A5CC7136Dd "callback(uint256)" 100 --network local
-
-Using network 'development'.
-
-Successfully requested relay entry with a callback. RequestId = 8
-
----Transaction Summary---
-From:0x23ba4cf58947d4eebd3b3aedcec28bec364b6727
-To:0x017a532a3bbb538753e84ae59d5131b0dfb7d2df
-BlockNumber:45
-TotalGas:139910
-TransactionHash:0xf345ef11c659157613c38366746a7053fd8aca59b854864629eab2b756c20196
---------------------------
-
-```
-
-== Internal Testnet
-
-Environment Name: `keep-dev`
-
-`keep-dev` is a cloud deployed instance of the keep-network complete
-with ETH chain. This environment is usually deployed with the latest
-`main` and is continuously deployed so uptime is variable.
-
-You do need a `keep-dev` VPN account to access the network and below
-endpoints. Reach out in the https://www.flowdock.com/app/cardforcoin/ops[DevOps flow] if you do not have one.
-
-=== Connection Info
-
-==== Ethereum Network
-
-- *Dashboard:* http://eth-dashboard.internal.keep-dev.com:3000
-- *Transactions:*
- ** _RPC:_ http://eth-tx-node.default.svc.cluster.local:8545
- ** _WebSocket:_ link:[ws://eth-tx-node.default.svc.cluster.local:8546]
-
-==== Keep Network
-
-- link:[keep-client-bootstrap-peer-0.default.svc.cluster.local:3919]
diff --git a/docs-v1/glossary.adoc b/docs-v1/glossary.adoc
deleted file mode 100644
index 7edec05cc9..0000000000
--- a/docs-v1/glossary.adoc
+++ /dev/null
@@ -1,62 +0,0 @@
-== Glossary
-
-Stake:: An amount of KEEP that is bonded in order to participate in the
- threshold relay and, optionally, the Keep network. Part or all of this can be
- removed from escrow as penalties for misbehavior, while part or all of it can
- be refunded if and when a participant chooses to withdraw in orderly fashion
- from the network and relay.
-
-Staker:: A staking client that has a stake, but may not yet be in a signing
- group.
-
-Minimum Stake Amount:: The minimum stake amount that will make a staking client
- a staker, as required by the staking smart contract.
-
-Stake Amount:: Total KEEP deposited for a single stake.
-
-Signing Member:: One member of one complete signing group in the threshold
- relay.
-
-Signing Group:: One complete signing group in the threshold relay.
-
-Lead Signing Group:: The signing group that will produce the next relay entry
- candidate (due to being the result of $E_i mod N$ with $E_i$ being the
- current entry and $N$ being the number of groups). If this group fails to
- respond to the request in time, the lead responsibility may shift to another
- group.
-
-Relay Entry Candidate:: A random number generated by the threshold relay that
- has not yet been finalized on the blockchain; may be invalid.
-
-Relay Entry:: A relay entry candidate that has been finalized on the blockchain;
- may be invalid.
-
-Keep Client:: The entire application running on a user's system, which contains
- multiple subclients for the various pieces of the Keep system.
-
-Staking Client:: The part of the Keep Client that stakes and participates in the
- threshold relay.
-
-Verifying Client:: Verifies entries on-chain and reports invalid entries.
- Optional, does not require a stake. Reward for identifying an invalid random
- number on the chain.
-
-Provider Client:: The Keep Provider piece of the application, which can in turn
- have workers for various Keep types.
-
-Keep Type:: The functionality that the given Keep relies on for providing
- security. e.g. an SHM (Secure Hardware Module) Keep, SMPC (Secure Multi-Party
- Computation) Keep, Proxy Reencryption Keep, etc.
-
-Provider Worker:: One worker that runs the code to allow a provider client to
- participate in a given Keep Type.
-
-Keep Provider:: One economic entity in the Keep network; has a stake, must
- participate in a signing group as a single member.
-
-Keep:: Up to 1MB of encrypted storage across one or more Keep Providers.
-
-KEEP:: Token used to stake. Can be represented as a K with a vertical bar
- through it.
-
-Keep Owner, Delegate, Requester are described in the whitepaper.
diff --git a/docs-v1/img-src/libp2p-join.tikz b/docs-v1/img-src/libp2p-join.tikz
deleted file mode 100644
index 9b994c9046..0000000000
--- a/docs-v1/img-src/libp2p-join.tikz
+++ /dev/null
@@ -1,23 +0,0 @@
-% !TEX root = ../relay-states.tex
-\tikz{
- \node[nested chain decision] (stake check) {\hyperref[fig:relay-group-initialization]{Staked?}};
-
- \node[state] (connecting) [right=2cm of stake check] {Connecting to bootstrap host};
-
- \node[state] (proving stake) [below=1cm of connecting] {Submitting stake proof};
-
- \node[state] (receiving peers) [below=1cm of proving stake] {Receiving peerlist};
-
- \node[nested chain decision] (state check) [left=2cm of receiving peers,text width=2cm] {\hyperref[fig:relay-group-initialization]{Checking\\current state}};
-
- \path [->] (stake check) edge node {Yes} (connecting)
-
- (connecting) edge node [pos=0.6] {connected} (proving stake)
- edge [bend right=30] node {failed to connect} (stake check)
-
- (proving stake) edge node [pos=0.7] {proof accepted} (receiving peers)
- edge [bend left=45] node [right,pos=0.6,text width=1.5cm] {proof rejected} (stake check)
-
- (receiving peers) edge node [centered,text width=1.4cm,align=flush center] {peers received} (state check)
- edge [bend left=30] node [left,pos=0.3] {failed to receive peers} (stake check)
-}
\ No newline at end of file
diff --git a/docs-v1/img-src/relay-diagram.tikz b/docs-v1/img-src/relay-diagram.tikz
deleted file mode 100644
index 849327cf45..0000000000
--- a/docs-v1/img-src/relay-diagram.tikz
+++ /dev/null
@@ -1,55 +0,0 @@
-% !TEX root = ../relay-states.tex
-\usetikzlibrary{shapes.multipart}
-\tikz[
- heading/.style={font=\bf},
- op/.style={draw,rectangle},
- plain/.style={minimum height=1cm},
- generic block/.style={draw,rectangle split,rectangle split parts=#1,minimum width=1cm,rectangle split empty part height=0.2mm},
- block/.style={draw,rectangle split,rectangle split parts=#1,minimum width=1cm,rectangle split empty part height=0.2mm},
-]{
- \node[heading] (chain) {Chain};
- \node[plain] (chain-elided) [below=0.1cm of chain.south] {...};
- \node[generic block] (pre-request) [below=of chain-elided.south] {};
- \node[block] (relay-request) [below=of pre-request.south] {\nodepart{two} Relay Request $r_i$};
- \node[generic block] (post-request) [below=of relay-request.south] {};
- \node[plain] (post-request-elided) [below=of post-request.south] {...};
- \node[block] (relay-entry-block) [below=of post-request-elided.south] {\nodepart{three} Relay Entry $v_i$};
-
- \path [<-,dashed] (chain-elided) edge (pre-request)
- (pre-request) edge (relay-request)
- (relay-request) edge (post-request)
- (post-request) edge (post-request-elided)
- (post-request-elided) edge (relay-entry-block);
-
- \node[plain] (seed-entry) [right=7.5cm of relay-request.two east] {$v_s$ - seed entry};
- \node[heading] (relay) [above=0.25cm of seed-entry] {Relay};
- \node[plain] (relay-entry) [right=7.5cm of relay-entry-block.three east] {$v_i$ - relay entry};
-
- \path [<-,dashed] (seed-entry) edge (relay-entry);
-
- \node[op] (relay-entry-seed-generation) [right=4cm of relay-request.two east] {$\times$};
- \node[plain] (relay-entry-seed) [below=of relay-entry-seed-generation] {$v_r$};
- \node[plain] (relay-entry-seed-label) [left=0 of relay-entry-seed] {``relay entry seed''};
- \node[op] (group-combiner) [below=of relay-entry-seed] {\texttt{fn}};
- \node[draw,rectangle split,rectangle split horizontal,rectangle split parts=2]
- (group-signature-fn) [below right=1cm and -0.7cm of group-combiner]
- {$G_i$ \nodepart{two} $S_{G_i}$};
- \node[plain] (signing-group-label) [left=0 of group-signature-fn] {``signing group"};
- \node[plain] (groupsig-function-label) [below right=-0.1cm and 0 of group-signature-fn.north east,text width=2.6cm,align=center] {``group signature\\function"};
- \node[plain] (group-signature) [right=4.75cm of relay-entry-block.three east] {$\sigma_{G_i}$};
- \node[plain] (groupsig-label) [below=-0.3cm and 0 of group-signature,minimum height=2ex] {``group signature''};
-
- \node[draw,circle,minimum width=2cm,minimum height=2cm] (groups) [left=of group-combiner] {Groups};
-
- \path [->] (relay-request.two east) edge (relay-entry-seed-generation)
- (seed-entry) edge (relay-entry-seed-generation)
- (relay-entry-seed-generation) edge (relay-entry-seed)
- (relay-entry-seed) edge (group-combiner)
- (groups) edge (group-combiner)
- (group-combiner) edge (group-signature-fn.one north)
- (group-signature-fn.two south) edge (group-signature);
- \draw [->] (relay-entry-seed) .. controls +($([yscale=0]group-signature-fn.two north) - ([yscale=0]relay-entry-seed)$) .. (group-signature-fn.two north);
-
- \path [->] (group-signature) edge (relay-entry)
- (group-signature) edge (relay-entry-block.three east)
-}
\ No newline at end of file
diff --git a/docs-v1/img-src/relay-entry-request-processing.tikz b/docs-v1/img-src/relay-entry-request-processing.tikz
deleted file mode 100644
index beff3ac194..0000000000
--- a/docs-v1/img-src/relay-entry-request-processing.tikz
+++ /dev/null
@@ -1,28 +0,0 @@
-% !TEX root = ../relay-states.tex
-\tikz{
- \node[nested state] (initialization) [text width=1.7cm] {\hyperref[fig:relay-group-initialization]{Pending Activation}};
-
- \node[chain state] (waiting) [right=of initialization,text width=1.5cm] {Waiting for request};
-
- \node[decision] (determining) [right=3cm of waiting,text width=2cm] {Is group responsible?};
-
- \node[state] (generating) [right=2cm of determining,text width=1.7cm] {Generating signature share};
-
- % Brodcasting? Might just be part of generating.
- \node[state] (verifying shares) [below=1cm of generating,text width=1.7cm] {Verifying shares};
-
- \node[chain state] (submitting) [left=3cm of verifying shares,text width=1.7cm] {Submitting signature};
-
- \path[->] (initialization) edge (waiting)
-
- (waiting) edge [chain transition] node {request received} (determining)
-
- (determining) edge [bend left=45] node [below] {no} (waiting)
- (determining) edge node {yes} (generating)
-
- (generating) edge [bend left=45] node [right,pos=0.45,text width=2cm] {share\\generated} (verifying shares)
-
- (verifying shares) edge node {signature ready} (submitting)
-
- (submitting) edge [chain transition,to path={[rounded corners=1.5cm] -| (\tikztotarget) \tikztonodes}] node [centered,pos=0.15,text width=2cm] {signature submitted} (waiting);
-}
diff --git a/docs-v1/img-src/relay-entry-verification.tikz b/docs-v1/img-src/relay-entry-verification.tikz
deleted file mode 100644
index 7f418b5413..0000000000
--- a/docs-v1/img-src/relay-entry-verification.tikz
+++ /dev/null
@@ -1,20 +0,0 @@
-% !TEX root = ../relay-states.tex
-\tikz{
- \node [start state] (start) {};
-
- \node [chain state] (waiting for entry) [right=of start,text width=1.8cm] {Waiting for relay entry};
-
- \node [decision] (verifying) [right=4cm of waiting for entry] {Is entry valid?};
-
- \node [chain state] (calling chain verification) [right=2cm of verifying,text width=1.8cm] {Calling on-chain verification};
-
- \path[->] (start) edge (waiting for entry)
-
- (waiting for entry) edge [chain transition] node {relay entry published} (verifying)
-
- (verifying) edge node {no} (calling chain verification)
- (verifying) edge [bend left=30] node [below,pos=0.55] {yes} (waiting for entry)
-
- % If on-chain verification fails do we back off?
- (calling chain verification) edge [chain transition,bend right=30] node {on-chain verification complete} (waiting for entry);
-}
diff --git a/docs-v1/img-src/relay-group-assignment.tikz b/docs-v1/img-src/relay-group-assignment.tikz
deleted file mode 100644
index 69bdaa4074..0000000000
--- a/docs-v1/img-src/relay-group-assignment.tikz
+++ /dev/null
@@ -1,17 +0,0 @@
-% !TEX root = ../relay-states.tex
-\tikz{
- \node [nested decision] (state check) [text width=2cm] {\hyperref[fig:relay-group-initialization]{Checking\\current state}};
-
- \node [state] (waiting for entry) [right=2cm of state check] {Waiting for relay entry};
-
- \node [decision] (checking) [right=3cm of waiting for entry] {Checking eligibility*};
-
- \node [nested state] (setting up group) [right=2cm of checking,text width=2cm] {\hyperref[fig:relay-group-setup]{Setting up group}};
-
- \path[->] (state check) edge node {no group} (waiting for entry)
-
- (waiting for entry) edge node [centered,text width=2cm,align=center] {relay entry published} (checking)
-
- (checking) edge [bend right=45] node {not eligible} (waiting for entry)
- edge node {eligible} (setting up group);
-}
diff --git a/docs-v1/img-src/relay-group-initialization.tikz b/docs-v1/img-src/relay-group-initialization.tikz
deleted file mode 100644
index 9d20c9fe18..0000000000
--- a/docs-v1/img-src/relay-group-initialization.tikz
+++ /dev/null
@@ -1,36 +0,0 @@
-% !TEX root = ../relay-states.tex
-\tikz{
- \node[start state] (start) {};
-
- \node[chain decision] (stake check) [right=of start] {Staked?\footnote{Local check to avoid doing unnecessary work.}};
-
- \node[nested state] (joining) [right=of stake check,text width=2cm] {\hyperref[fig:libp2p-join]{Joining\\\tt{libp2p}}};
-
- \node[chain decision] (state check) [below=2cm of joining] {Checking\\current state};
-
- \node[nested state] (waiting) [below left=3cm of state check,text width=2cm] {\hyperref[fig:relay-group-assignment]{Waiting\\for group}};
- \node[nested state] (setting up group) [below right=3cm of waiting,text width=2cm] {\hyperref[fig:relay-group-setup]{Setting up group}};
-
- \node[nested state] (processing) [below right=3cm of state check,text width=1.7cm] {\hyperref[fig:relay-entry-request-processing]{Processing requests}};
-
- \path [->] (start) edge (stake check)
-
- (stake check) edge [chain transition,bend right=45] node [above] {No} (start)
- (stake check) edge [chain transition] node [above] {Yes} (joining)
-
- % NOTE We may not want to return to the stake check on failed join,
- % NOTE we may just want to abort.
- (joining) edge [bend right=45] node [above] {failed to join} (stake check)
- (joining) edge node {joined} (state check)
-
- (state check) edge [chain transition,bend right=40] node [left] {no group} (waiting)
- edge [chain transition] node [pos=0.6,text width=3cm,align=flush center] {in uninitialized group} (setting up group)
- edge [chain transition,bend left=40] node [right] {in initialized group} (processing)
-
- (waiting) edge [bend left=40] node [left,pos=0.75,text width=2cm,align=flush center] {assigned to group} (setting up group)
-
- (setting up group) [bend left=40] edge node [left] {setup failed} (waiting)
- (setting up group) [bend right=40] edge node [right] {group activated} (processing)
-
- (processing) [bend left=40] edge node [right,pos=0.75,text width=2cm,align=flush center] {group dissolved} (state check)
-}
\ No newline at end of file
diff --git a/docs-v1/img-src/relay-group-setup.tikz b/docs-v1/img-src/relay-group-setup.tikz
deleted file mode 100644
index ff01d3b2b3..0000000000
--- a/docs-v1/img-src/relay-group-setup.tikz
+++ /dev/null
@@ -1,54 +0,0 @@
-% !TEX root = ../relay-states.tex
-\tikz{
- \node[nested state,text width=2cm] (waiting) {\hyperref[fig:relay-group-initialization]{Waiting for group}};
-
- \node[chain state] (awaiting entry) [right=of waiting] {Awaiting\\relay entry};
-
- \node[decision] (eligibility check) [right=2.5cm of awaiting entry] {Eligible for group?};
-
- \node[state] (joining channel) [right=2cm of eligibility check] {Joining broadcast channel};
-
- \node[state] (generating) [below left=1cm and 3cm of joining channel] {Generating secret key share and proofs};
-
- \node[state] (announcing) [left=2cm of generating] {Announcing secret key proofs};
-
- \node[decision] (verifying) [below=1cm of announcing] {Verifying other proofs};
-
- % FIXME Accusation process is incomplete and might be its own sub-diagram.
- \node[state] (accusing) [below right=-0.8cm and 2cm of verifying] {Publishing invalidity accusation};
- \node[state] (generating pubkey) [below left=2cm of verifying.south] {Generating public key};
-
- \node[chain state] (submitting pubkey) [right=2cm of generating pubkey] {Submitting public key};
-
- \node[chain state] (awaiting pubkey) [below=1cm of submitting pubkey] {Awaiting on-chain public key};
-
- \node[state] (pending activation delay) [right=2cm of awaiting pubkey] {Waiting for activation delay};
-
- \node[nested state] (processing) [below=4cm of joining channel,text width=2cm] {\hyperref[fig:relay-entry-request-processing]{Processing requests}};
-
- \path [->] (waiting) edge (awaiting entry)
-
- (awaiting entry) edge [chain transition] node [above] {entry received} (eligibility check)
-
- (eligibility check) edge [bend right=45] node [above] {No} (awaiting entry)
- edge [pos=0.6] node {Yes} (joining channel)
-
- (joining channel) edge [bend right=30] node {joining failed} (waiting)
- edge node [sloped] {joined} (generating)
-
- (generating) edge node [centered,text width=1.5cm,align=flush center] {shares generated} (announcing)
-
- (announcing) edge [pos=0.65] node {shares announced} (verifying)
-
- (verifying) edge node [centered,text width=1.5cm,align=flush center] {invalid share} (accusing)
- edge [pos=0.65] node {shares valid} (generating pubkey)
-
- (generating pubkey) edge node {generated} (submitting pubkey)
-
- (submitting pubkey) edge [chain transition,pos=0.65] node {submitted} (awaiting pubkey)
-
- (awaiting pubkey) edge [chain transition,to path={[rounded corners=3cm] -| (\tikztotarget) \tikztonodes}] node [pos=0.15,centered,text width=2cm] {relay entry received} (waiting)
- edge [chain transition] node [centered,text width=1.5cm,align=flush center] {pubkey published} (pending activation delay)
-
- (pending activation delay) edge [bend right=15] node [right,text width=2cm] {activation delay elapsed} (processing)
-}
\ No newline at end of file
diff --git a/docs-v1/img-src/startup-diagram.tikz b/docs-v1/img-src/startup-diagram.tikz
deleted file mode 100644
index c472d8056f..0000000000
--- a/docs-v1/img-src/startup-diagram.tikz
+++ /dev/null
@@ -1,14 +0,0 @@
-% -*- root: relay-states-preview.tex -*-
-
-\tikz[every node/.style={node distance=2cm},
- fan out/.style={to path={-- ++(0.5,0) -| ($ (\tikztotarget) - (1,0) $) -- (\tikztotarget)}}]{
- \node[draw,circle] (start) {};
-
- \node[thread] (group participation) [above right=2cm and 2cm of start] {\hyperref[fig:relay-group-initialization]{Relay group participation}};
- \node[thread] (verification) [right=of start] {\hyperref[fig:relay-entry-verification]{Relay entry verification}};
- \node[thread] (keep client) [below right=2cm and 2cm of start] {\hyperref[fig:keep-client-initialization]{Keep client}};
-
- \path [->] (start) edge [fan out] (group participation.west)
- (start) edge [fan out] (verification.west)
- (start) edge [fan out] (keep client.west);
-}
diff --git a/docs-v1/monitoring-and-alerting.adoc b/docs-v1/monitoring-and-alerting.adoc
deleted file mode 100644
index ba49bfcbda..0000000000
--- a/docs-v1/monitoring-and-alerting.adoc
+++ /dev/null
@@ -1,97 +0,0 @@
-:toc: macro
-
-= Monitoring and Alerting for Keep Nodes
-
-toc::[]
-
-Operators on the Keep network are typically running two client executables,
-generally on separate nodes. These clients each join a separate libp2p network,
-one for the Keep random beacon and one for the Keep ECDSA system used to back,
-amongst other things, tBTC.
-
-Below are some important metrics and alerting guidelines that apply to both
-clients.
-
-== Important Metrics
-
-Clients report information in two primary ways: a metrics endpoint accessible
-via HTTP and the logs that are printed from the client. Logs have levels that
-correspond to message severity.
-
-As such, the most important metrics to track for all Keep nodes are:
-
-* WARN log count over time
-* ERROR log count over time
-* CRITICAL log count over time
-* Peer count over time (accessible at `/metrics` on the port configured in the
- `Metrics` block of the configuration file.)
-* ETH balance of the operator account
-
-The client can be configured to log ERROR-level logs when the ETH balance of the
-operator account drops below a set level; look for `BalanceAlertThreshold` in
-the sample configuration file for more.
-
-For ECDSA clients, in addition to these metrics, it’s recommended that you
-track the keeps that a given node is participating in. You can track these by
-looking for log messages in the format:
-
-```
-member [%s] is starting signer generation for keep [%s]...
-```
-
-These indicate keep opening, with the first `%s` being the operator address
-and the second being the keep address. Keep closing or termination can be
-spotted by looking for log messages in the format:
-
-```
-unsubscribing from events on keep terminated
-unsubscribing from events on keep closed
-```
-
-These currently do not include the keep address, though they will be updated to do so.
-
-== Alerting and Notification Thresholds
-
-The guidelines below distinguish between **notifications**, which are
-informational but not necessarily interruptive, and **alerts**, which should
-trigger pages and lead to quick investigation. The guidelines also
-distinguish between different likelihoods of fund loss. Recommended
-thresholds are as follows:
-
-* More than 5 WARN logs over 5 minutes should result in a **notification** for
- on-call personnel for closer monitoring. These are typically
- connectivity-related, and can be precursors to larger issues if remediation
- is not applied. Fund loss may or may not occur without intervention if
- warnings do not stop.
-* More than 10 WARN logs over 15 minutes should result in **alerts** that will
- trigger pages for on-call personnel. As above, these can be precursors to
- larger issues without remediation. Fund loss is possible without
- intervention.
-* ERROR and CRITICAL logs should result in escalated **alerts** that will
- trigger pages for on-call personnel. CRITICAL logs are generally associated
- with a node crash. Both are a high-signal indicator that the node is
- experiencing issues that have already led to on-chain problems or will soon
- do so. Fund loss is probable without intervention.
-* Peer counts that drop by more than 5% in a 10-minute period should result in
- a **notification** for on-call personnel for closer monitoring. These may
- or may not be due to the node itself, but can be precursors to larger
- issues if not investigated. Fund loss may or may not occur without
- intervention if these counts do not recover.
-* Peer counts that drop by more than 10% and remain dropped for a 20-minute
- period should result in **alerts** that will trigger pages for on-call
- personnel. These may or may not be due to the node itself, but can be
- precursors to larger issues if not investigated. If the issues don’t seem
- to be with the node but with one of its peers, it’s highly recommended to
- engage with the community Discord to try and find the relevant operator.
- Fund loss is possible without intervention if the problematic node is
- participating in a keep with the node you are operating.
-* Operator ETH balance below 0.5 ETH should result in a **notification** for
- on-call personnel for closer monitoring. This is a high safety margin, but
- should result in close monitoring of balance and start the process for
- topping the operator account up.
-* Operator ETH balance below 0.2 ETH should result in **alerts** that will
- trigger pages for on-call personnel. ETH balance below 0.2 ETH can quickly
- deplete in cases of high network activity, so replenishing it is high
- priority. Fund loss is possible without intervention if the node in
- question fails to participate in a critical operation (e.g. a redemption
- signature or a signer setup).
\ No newline at end of file
diff --git a/docs-v1/random-beacon/README.adoc b/docs-v1/random-beacon/README.adoc
deleted file mode 100644
index 66dc4a7f81..0000000000
--- a/docs-v1/random-beacon/README.adoc
+++ /dev/null
@@ -1,30 +0,0 @@
-= Keep Random Beacon Work-in-progress Yellowpaper
-
-This directory contains a yellowpaper/specification for the Keep random
-beacon, which will initially be built out for Ethereum. The yellowpaper
-is currently still a work-in-progress, and is being developed alongside
-the core beacon code.
-
-The core beacon code will be shared at a later time, while the yellowpaper, and
-its progress, are available now. Note that core yellowpaper progress is still
-handled in the Keep monorepo; we are syncing the branch history to and from
-this repository on an ongoing basis.
-
-The yellowpaper is written in AsciiDoc and built using
-https://asciidoctor.org[Asciidoctor]. It renders directly in GitHub, so please
-feel free to click through the files in GitHub to see the rendered content,
-starting with <>. Notably, GitHub does not process
-inter-file includes, so includes are rendered as links to the embedded files.
-
-You can also see a fully-built version of the yellowpaper at
-http://docs.keep.network/random-beacon/, or, if you prefer a PDF version, at
-http://docs.keep.network/random-beacon/index.pdf.
-
-== Building
-
-To build the yellowpaper yourself, you should
-https://asciidoctor.org/#installation[install Asciidoctor]. Then you can enter
-the root directory of this repository and run `asciidoctor index.adoc` to
-produce an `index.html` file. Asciidoctor also supports several
-https://asciidoctor.org/docs/user-manual/#selecting-an-output-format[other
-output formats].
diff --git a/docs-v1/random-beacon/alt_bn128.adoc b/docs-v1/random-beacon/alt_bn128.adoc
deleted file mode 100644
index 4fac5d1c86..0000000000
--- a/docs-v1/random-beacon/alt_bn128.adoc
+++ /dev/null
@@ -1,48 +0,0 @@
-==== Elliptic curve specifications
-
-The pairing operations of the random beacon are performed on the curve
-`alt_bn128`, as specified below:
-
-[horizontal]
-q::
-`21888242871839275222246405745257275088548364400416034343698204186575808495617`
-+
-Order of the groups G1 and G2
-
-p::
-`21888242871839275222246405745257275088696311157297823662689037894645226208583`
-+
-The size of the field _F~p~_ used in `alt_bn128`
-
-G1::
-Cyclic group of order _q_ on the curve `Y^2 = X^3 + 3` over the field _F~p~_
-with generator _P1_
-+
-Any point on the curve is a member of _G1_
-
-P1::
-`(1, 2)`
-+
-Generator of _G1_
-
-G2::
-Cyclic group of order _q_ on the curve `Y^2 = X^3 + 3/(i+9)` over the field
-`F_p^2 = F_p[i] / (i^2 + 1)` with generator _P2_
-+
-Points on the curve that have order _q_ are members of _G2_
-
-P2::
-{blank}
-+
-....
-(
- 11559732032986387107991004021392285783925812861821192530917403151452391805634 * i +
- 10857046999023057135944570762232829481370756359578518086990519993285655852781,
- 4082367875863433681332203403145435568316851327593401208105741076214120093531 * i +
- 8495653923123431417604973247489272438418190587263600148770280649306958101930
-)
-....
-+
-Generator of _G2_
-
-These terms deviate from the standard naming conventions.
diff --git a/docs-v1/random-beacon/authorizations.adoc b/docs-v1/random-beacon/authorizations.adoc
deleted file mode 100644
index 36f731155e..0000000000
--- a/docs-v1/random-beacon/authorizations.adoc
+++ /dev/null
@@ -1,197 +0,0 @@
-:toc: macro
-:toclevels: 4
-
-= Roles and authorizations
-
-ifndef::yellowpaper[toc::[]]
-
-== Roles
-
-Governance::
-
-Governance is the final arbiter of authority in the Keep Network.
-The role of Governance is to enable recovery from key compromise
-by rekeying other roles.
-Governance has the authority to change the addresses of
-the _Registry Keeper_, _Panic Button_,
-and the service contracts' _Operator Contract Upgraders_
-The rekeying process is currently unspecified.
-
-Registry Keeper::
-
-The Registry Keeper maintains the global _registry_ of approved contracts.
-Each operator contract must be approved by the Registry Keeper
-before it can be authorized to punish operators
-or used by a service contract.
-The Registry Keeper can be rekeyed by _Governance_.
-
-Panic Button::
-
-The Panic Button can disable malicious or malfunctioning contracts
-that have been previously approved by the Registry Keeper.
-When a contract is disabled by the Panic Button,
-its status on the _registry_ changes to reflect this,
-and it becomes ineligible to penalize operators.
-Contracts disabled by the Panic Button can not be reactivated.
-The Panic Button can be rekeyed by _Governance_.
-
-Operator Contract Upgrader::
-
-Each service contract has an Operator Contract Upgrader
-whose purpose is to manage operator contracts for that service contract.
-The Operator Contract Upgrader
-can add new operator contracts to the service contract,
-and deprecate old ones.
-The Operator Contract Upgraders can be rekeyed by _Governance_.
-
-Authorizer::
-
-Each operator has an Authorizer
-whose purpose is to determine which operator contracts
-may punish the operator for misbehavior.
-The operator can only perform work for authorized operator contracts.
-The Authorizer cannot be rekeyed except by undelegating and redelegating.
-
-== Authorizations
-
-=== The Registry and Panic Button
-
-The registry tracks all Keep Org -approved contracts.
-Operator contracts have a special status on the registry,
-reflecting the ability of the Panic Button to disable them.
-
-Each operator contract's status may be `NULL`, `APPROVED` or `DISABLED`.
-
-A status of `NULL` is the default
-and means that the operator contract has not been approved
-by the _Registry Keeper_.
-
-When the _Registry Keeper_ approves a operator contract,
-its status switches to `APPROVED` in the registry.
-Approved operator contracts can be authorized to punish operators,
-and service contracts may utilize them.
-
-The _Panic Button_ can be used
-to set the status of an `APPROVED` contract to `DISABLED`.
-Operator Contracts disabled with the _Panic Button_ cannot be re-enabled,
-and disabled contracts may not punish operators
-nor be selected by service contracts to perform work.
-
-=== Staking contracts: authorized operator contracts
-
-Staking contracts hold staked tokens,
-enforce staking rules,
-and punish misbehaving operators
-on behalf of authorized operator contracts.
-For this purpose,
-each staking contract tracks which operator contracts
-have been authorized by which addresses.
-
-The _authorized operator contracts_ are a mapping
-of `(address authorizer, address operator_contract) -> status`.
-
-The status of a contract may be either `NULL` or `AUTHORIZED`.
-A status of `NULL` is the default
-and means the operator contract is not authorized.
-A status of `AUTHORIZED` means that the operator contract
-may impose punishments on those operators
-who have assigned that `authorizer` as their _Authorizer_.
-
-To authorize an operator contract on a staking contract,
-the operator contract must have been `APPROVED` on the _registry_.
-Once a operator contract has been authorized,
-authorization cannot be withdrawn by the authorizer.
-However, a operator contract that has been `DISABLED` by the _Panic Button_
-may not punish stakers.
-
-=== Service contracts: used operator contracts
-
-Service contracts use the basic functionality performed by operator contracts,
-to provide useful services to the public.
-Service contracts can use multiple different versions of operator contracts
-to perform the operator contract functions.
-To permit system upgrades,
-the list of used operator contracts can be updated with proper authorization.
-
-A service contract is deployed with zero operator contracts,
-rendering the service contract inactive
-until at least one operator contract is activated.
-
-Each service contract has its own _Operator Contract Upgrader_
-who can add used operator contracts.
-To add a used operator contract,
-the operator contract must have been `APPROVED` on the _registry_,
-and the interface it claims to implement
-must match what the service contract expects.
-
-If an operator contract has been `DISABLED` by the _Panic Button_,
-the service contract must not use its functionality.
-This must be checked when the service contract selects an operator contract.
-
-== Impact of compromised keys
-
-=== Individual keys
-
-==== Registry Keeper
-
-A compromised Registry Keeper can approve arbitrary operator contracts.
-However, using those operator contracts for a service contract
-requires the service contract's Operator Contract Upgrader as well.
-Thus, a compromised Registry Keeper cannot endanger customers alone.
-Similarly, stakers' funds are safe from being slashed by malicious contracts
-unless their Authorizers are also compromised.
-
-==== Panic Button
-
-A compromised Panic Button can disable arbitrary operator contracts
-and halt all network services.
-Recovery is impossible until Governance has rekeyed the Panic Button.
-
-This is inevitable due to the functionality of the Panic Button,
-but the impact could be mitigated
-by setting a cap on how many times the Panic Button can be invoked
-within a particular timeframe.
-However, if a compromised Registry Keeper
-approves a large number of malicious contracts,
-a rate-limited Panic Button would be overwhelmed
-and unable to disable them all.
-This could be further mitigated by rate-limiting the Registry Keeper similarly.
-
-==== Operator Contract Upgrader
-
-A compromised Operator Contract Upgrader
-can activate operator contracts on the affected service contract
-within the strict constraints of the upgrade process.
-It is unlikely that an uncompromised Registry Keeper
-would have approved an operator contract that would satisfy the constraints
-yet cause a significant impact on the service contract.
-
-==== Authorizer
-
-If only the Authorizer of some staker is compromised,
-the attacker can authorize operator contracts
-that have been approved by the Registry Keeper,
-and that use the same staking contract as the staker.
-
-This has a very limited negative impact
-unless the Registry Keeper has approved
-a faulty or malicious operator contract.
-
-=== Key combinations
-
-==== Registry Keeper + Operator Contract Upgrader
-
-If a malicious operator contract can get globally approved,
-the impacted service contract can be completely subverted
-by switching all work to the malicious operator contract.
-
-While already existing operations should finish normally,
-the service contract can be rendered effectively useless for new requests.
-
-==== Registry Keeper + Authorizer
-
-If the Registry Keeper approves a malicious operator contract,
-and a staker's Authorizer authorizes it,
-the malicious contract can be used to steal staked funds
-within the constraints of tattletale rewards:
-seizing up to 5% to the attacker and burning the rest.
diff --git a/docs-v1/random-beacon/beacon-pricing.py b/docs-v1/random-beacon/beacon-pricing.py
deleted file mode 100644
index 867492ecd1..0000000000
--- a/docs-v1/random-beacon/beacon-pricing.py
+++ /dev/null
@@ -1,147 +0,0 @@
-class Bid(NamedTuple):
- amount: Money
- expiresAt: Blockheight
- seedCommitment: Commitment[SeedValue]
-
-
-class BidPool(NamedTuple):
- bidTotal: Money
- allBids: OrderedList[Bid]
-
-
-def popBid(
- pool: BidPool
-) -> Option[Bid]:
- if empty(pool.allBids):
- return False
- else:
- topBid = pool.allBids.head
- remainingBids = pool.allBids.tail
-
- pool.bidTotal -= topBid.amount
- pool.allBids = remainingBids
-
- return topBid
-
-
-def pushBid(
- pool: BidPool,
- bid: Bid
-) -> BidPool:
- pool.bidTotal += bid.amount
- pool.allBids = addToOrderedList(pool.allBids, bid)
-
- return pool
-
-
-def filterExpired(
- pool: BidPool,
- currentTime: Blockheight
-) -> BidPool:
- filteredPool = BidPool(0, [])
-
- # for conceptual simplicity, we create a new pool containing
- # only unexpired bids, then overwrite the old pool with it
- for bid in pool.allBids:
- if bid.expiresAt > currentTime:
- pushBid(filteredPool, bid)
-
- pool = filteredPool
- return filteredPool
-
-
-def tick(
- pool: BidPool,
- newBids: List[Bid]
-) -> Option[BeaconOutput]:
-
- # add in new bids
- for bid in newBids:
- pushBid(pool, bid)
-
- # remove expired bids
- filterExpired(pool, getCurrentBlockHeight())
-
- # the heavy lifting function
- # the current price should be determined by how many outputs the beacon
- # has recently generated; a larger number of outputs means higher price
- currentPrice = getCurrentOutputPrice()
-
- if pool.bidTotal >= currentPrice:
- return generateOutput(pool, currentPrice)
- else:
- return False
-
-
-def generateOutput(
- pool: BidPool,
- currentPrice: Money
-) -> Option[BeaconOutput]:
- usedBids = BidPool(0, [])
-
- while usedBids.bidTotal < currentPrice:
- nextBid = popBid(pool)
- pushBid(usedBids, nextBid)
-
- # determine the total stake for this output generation,
- # and then individual stakers' stake
- #
- # higher bids -> higher stake
- #
- # note that the actual rewards for stakers will be proportionally higher
- # when bids and stakes are higher, due to costs being constant
- #
- # thus highest stakes create the best risk:reward ratio
- totalStake = usedBids.bidTotal * BID_STAKE_MULTIPLIER
- memberStake = totalStake / N
-
- # an alternative algorithm, creating more variability in the stakes
- #
- # getCurrentGasPrice() is a simplification and should actually use
- # a smoother estimate to correct for price fluctuations
- totalProfit = usedBids.bidTotal - (getCurrentGasPrice() * OUTPUT_GAS_COST)
- totalStake = totalProfit * BID_STAKE_MULTIPLIER
- memberStake = totalStake / N
-
- # select the group to perform the beacon output
- # based on the hash of the block containing the transaction
- # triggering the output generation
- generationGroup = selectGroup(getLatestBlockHash())
-
- # use some defined function to determine the time we will
- # wait for any single bidder to reveal their seed
- requestTimeout = timeoutByBidN(len(usedBids.allBids))
-
- startingTime = getCurrentBlockHeight()
- timeoutBlock = startingTime + requestTimeout
-
- # initially, the top bid is eligible to reveal seed
- eligibleBid = popBid(usedBids)
-
- revealedSeed = False
-
- while revealedSeed == False:
- # reached timeout -> top bidder no longer eligible
- # next highest bidder becomes eligible
- if getCurrentBlockHeight() >= timeoutBlock:
- timeoutBlock += requestTimeout
- eligibleBid = popBid(usedBids)
-
- # nobody responds within timeout, no output produced
- if not eligibleBid:
- return False
-
- seedValue = receiveSeedRevealTx()
-
- if checkCommitment(seedValue, eligibleBid.seedCommitment):
- revealedSeed = seedValue
-
- # we have a revealed seed, time to proceed with generation
- output = generationGroup.sign(revealedSeed, v_previous)
- if not empty(output.misbehavingMembers):
- penalize(output.misbehavingMembers, memberStake)
-
- return output
-
-
-
diff --git a/docs-v1/random-beacon/contract-structure.adoc b/docs-v1/random-beacon/contract-structure.adoc
deleted file mode 100644
index 89f1b23478..0000000000
--- a/docs-v1/random-beacon/contract-structure.adoc
+++ /dev/null
@@ -1,112 +0,0 @@
-:toc: macro
-:toclevels: 4
-
-= Contract structure
-
-ifndef::yellowpaper[toc::[]]
-
-== Overview
-
-Token contract::
-
-KEEP is an ERC20 token defined by the _token contract_.
-The token contract is hard-coded in the operator and staking contracts,
-but the design of the overall system makes it possible
-to later migrate to a new version of the token contract
-without disrupting customer experience.
-
-Staking contract::
-
-Owners of KEEP tokens can use a _staking contract_
-to _stake_ them and use them as collateral for _operators_
-who perform useful work in the Keep Network.
-Staked tokens are transferred to the staking contract
-and _delegated_ to an operator address.
-The staking contract makes the tokens available to _operator contracts_
-that have been _authorized_ to punish the operator in case of misbehavior,
-while protecting them from unauthorized operator contracts.
-
-Operator contracts::
-
-Operators interact with _operator contracts_
-to perform useful work for customers.
-Operator contracts handle operations
-that are critical for the proper incentives of individual operators.
-They reward operators for correct behavior,
-and are authorized to punish misbehavior.
-
-Service contracts::
-
-_Service contracts_ provide higher-level services to the public
-using work performed by one or more operator contracts.
-Service contracts do not interact directly with operators
-nor do they need to be aware of the KEEP tokens or the staking contract.
-Operator contracts can be upgraded without disrupting customer experience
-by deploying a new version and adding it to the service contract.
-
-Registry::
-
-The addresses of contracts approved by Keep Org are kept in the _registry_.
-Token contracts, staking contracts, operator contracts and service contracts
-are all tracked separately in the registry.
-The addresses and statuses of various contracts
-can be queried from the registry.
-
-== Operator contracts
-
-Operator contracts coordinate the work performed by network operators,
-and provide services to other "customer" contracts.
-Operator contracts handle all operations
-that may have an impact on staked tokens.
-Conversely, operators performing work for the network
-only need to interact with operator contracts.
-
-The customer contract is treated as untrusted
-and the operator contract must maintain correctness
-and the safety of the operators' stakes
-regardless of the customer contract's input.
-Each operator contract is an independent "microservice",
-keeping its own state on security-critical data.
-
-When a customer contract requests an operator contract to perform a service,
-it must pay the operator contract for the service provided.
-The payment is distributed to contributing operators
-according to the operator contract's own rules.
-An operator contract can either provide services
-to any contract that makes a valid request and pays the correct fee,
-or it can be owned by a specific contract and only serve its owner.
-In the random beacon
-the service contract is the only "customer" of the operator contracts,
-and operator contracts only provide services to the random beacon.
-Future operator contracts may provide services directly to the public.
-
-If one or more participant operators misbehave
-or fail to perform promised work,
-the operator contract tells the staking contract to punish the guilty parties
-and optionally reward a tattletale that proved the misbehavior.
-To punish misbehaving operators,
-an operator contract must be authorized by the operator's authorizer.
-Once an operator contract has been authorized by some address,
-it can never be deauthorized by that address.
-
-== Service contracts
-
-Service contracts use the basic functionality
-performed by operator contracts,
-to provide useful services to the public.
-In contrast to operator contracts,
-service contracts don't interact directly with operators
-and a failure in a service contract cannot risk operators' stakes.
-
-Service contracts receive requests for their services from customers,
-and provide the requested services.
-Elements that are critical for operators' security and incentives
-are delegated to an operator contract,
-while other parts of the work are performed in the service contract.
-The service contract keeps shared state which is not security-critical.
-
-Service contracts can use
-multiple different versions of operator contracts
-to perform the operator contract functions.
-To permit system upgrades,
-the list of used operator contracts can be updated with proper authorization.
diff --git a/docs-v1/random-beacon/delegation-notes.adoc b/docs-v1/random-beacon/delegation-notes.adoc
deleted file mode 100644
index 0571a6428f..0000000000
--- a/docs-v1/random-beacon/delegation-notes.adoc
+++ /dev/null
@@ -1,544 +0,0 @@
-= Stake delegation - notes
-
-Based on RFC 3
-
-Network throughput only depends on atomic stakes vs multioperation, ie whether
-you lock the stake (which means every operation locks MINIMUM_STAKE as holders
-will simply divide their stakes over the largest possible number of addresses if
-the full stake is locked) or permit "fractional reserve staking" where the same
-MINIMUM_STAKE may back up multiple different operations at the cost of being
-able to pull off an "exit scam" style misbehaviour where someone who is going to
-get their stake slashed away entirely misbehaves on all their other operations
-as well.
-
-Since the average level of stake leveraging this way is going to be the same for
-both honest and malicious participants, the effect of this on network integrity
-is ultimately probabilistically constrained and anomalously high leverages (eg.
-someone with 2 * MINIMUM_STAKE participating in 20 operations when typically
-someone with MINIMUM_STAKE participates in 3) would be correspondingly rare.
-
-Thus the real outcome is:
-
-With atomic staking, the network throughput is hard-capped at TOTAL_SUPPLY /
-MINIMUM_STAKE operations simultaneously. This necessitates adjusting
-MINIMUM_STAKE downwards if there is significant growth in the network usage.
-However, if the value of the tokens scales linearly with usage, the amounts at
-stake remain constant in external money.
-
-The need to adjust MINIMUM_STAKE down over time also means that barriers to
-entry to staking should remain constant, and ownership of tokens would be free
-to get distributed more widely.
-
-With unrestricted multioperation the network throughput is not limited by the
-supply/stake ratio, and increased demand just means the same stakes get used for
-multiple different operations if MINIMUM_STAKE remains constant. If the value of
-the tokens increases with network usage, this means that the price of "random"
-misbehaviour also increases, and acts as a serious incentive to ensure
-reliability on a more mature network, but when failures happen there is less
-incentive to not misbehave further. However, the total amount of misbehaviour
-one can afford with a constant external money amount is limited to a small
-multiplier of the amount under atomic staking.
-
-If MINIMUM_STAKE stays constant, it increases the barriers to entry to staking
-and encourages concentration of tokens in fewer, richer hands. However, if
-multioperation is combined with downwards adjustment in minimum stake (and
-penalties, which both of these imply should be defined as fractions of the
-minimum stake), its behaviour ends up being a hybrid of unadjusted
-multioperation and fully adjusted atomic staking (or, if the minimum stake is
-completely adjusted for network demand, similar to that with atomic staking
-except with a small chance of stakes being leveraged), but all forms of
-unrestricted multioperation offer unlimited throughput.
-
-'''
-
-Because all forms of atomic staking are isomorphic due to the incentive
-structure created by positive expected value from network participation, it
-seems that these proposals actually break down into the following:
-
-- atomic staking vs. multioperation
-- dynamic vs. constant MINIMUM_STAKE
-- instant undelegation with penalties vs. delayed undelegation with stake
-locking
-
-'''
-
-If the above are condensed into letters denoting particular combinations:
-
-A : M +
-D : C +
-P : L
-
-I think anything from xxP is not very viable because of the
-problems with instant undelegation, and thus xxL is the design space I'd
-recommend. ACL has inherently limited throughput and is not a long-term viable
-option. This leaves ADL, MDL and MCL .
-
-MCL is the simplest to implement because it avoids the need to adjust the
-minimum stake (This scheme is not present in this RFC; options 1 and 3
-correspond to AxL of which ADL is a viable option, while 2 is MxP and 4 is AxP,
-not recommended because of instant undelegating). MDL is more complex but also
-more flexible if changes in the token staking patterns are desired. ADL is
-slightly more intuitive in its characteristics in resistance to misbehaviour,
-but it's also inflexible in how the minimum stake has to be adjusted to keep up
-with demand, and it may present problems with accommodating possible future
-services with especially high per-member stake requirements.
-
-'''
-
-There is also the option of keeping MINIMUM_STAKE constant but adjusting
-penalties to match increase in demand and effective leveraging of multioperated
-stakes. This would also enable particularly high-assurance services as the
-maximum money at stake effectively grows with network demand.
-
-'''
-
-N~max_stakers~::
-Tokens~total~ / Stake~min~
-+
-The maximum count of stakers if all tokens were distributed in exact integer
-multiples of _Stake~min~_
-
-N~stakers~::
-sum(map(Stake~i~ -> floor(Stake~i~/Stake~min~), Stakers))
-+
-The actual number of virtual stakers available in the network
-
-c::
-N~stakers~ / N~max_stakers~
-+
-The staking efficiency factor of the network; what fraction of the tokens is
-"actually performing work"
-
-Ops::
-min(Ops~max~, Demand)
-+
-The amount of simultaneous operations being performed
-
-o::
-Ops / N~stakers~
-+
-The overcapacity factor; how many simultaneous operations the average virtual
-staker is performing
-
-Ops~max~::
-o~max~ * N~stakers~ +
-f~ops~ * Demand
-
-The maximum amount of simultaneous operations the network can perform
-
-o~max~::
-The maximum overcapacity factor
-
-Price::
-f~price~ * Demand
-+
-Token price assuming it follows network demand linearly; argument for this:
-+
-Expected value from operating is _EV = R * o - OpCost = (R - f~op_cost~) * o_
-+
-Let _CapCost_ be cost of capital and ignore some constant factors.
-+
-Operating a node is profitable when _EV > Stake~min~ * Price * CapCost_.
-+
-_R * o > Stake~min~ * Price * CapCost_ +
-_R * Ops / N~stakers~ > Stake~min~ * Price * CapCost_ +
-_R * Demand / (Tokens~total~ / Stake~min~) > Stake~min~ * Price * CapCost_ +
-_R * Demand / Tokens~total~ > Price * CapCost_ +
-_(R / Tokens~total~) * Demand > Price * CapCost_
-+
-Thus equilibrium at _Price = Demand * R / (Tokens~total~ * CapCost)_
-(and the ignored constant factors).
-
-OpCost::
-f~op_cost~ * o
-+
-The cost of operating a node (assuming cost follows network demand linearly)
-
-Stake~actual~::
-Stake~min~ * Price
-+
-The actual amount of money at stake with network operations
-
-'''
-
-Proposal 1:
-
-- 1:1 owner address/operator address
-- atomic stake
-- delayed undelegation
-
-o~max~ = 1
-Ops~max~ = N~stakers~
-
-Because of the 1:1 nature and atomicity, stakes will be blitzpantsed. Thus there
-will be _N~stakers~_ capacity in the network. This requires
-_N~stakers~ = Demand_ and further _c * (Tokens~total~ / Stake~min~) = Demand_
-or _Stake~min~ = c * (Tokens~total~ / Demand)_
-
-Name _c' = c * Tokens~total~_; now _Stake~min~ = c' / Demand_
-
-'''
-
-Proposal 2:
-
-- 1:1 owner/operator
-- multioperation
-- instant/penalized undelegation
-
-o~max~ = unlimited
-Ops~max~ = unlimited
-
-No specific incentive to blitzpants. No specific need to adjust _Stake~min~_.
-
-_Stake~actual~ = Stake~min~ * f~price~ * Demand_;
-with _p = Stake~min~ * f~price~_: _Stake~actual~ = p * Demand_
-
-The risk of "free" misbehavior when _D~sum~ > Stake~min~_ is mostly illusory.
-The maximum penalty _S~i~_ could earn is _D~max_i~ = o~i~ * Stake~min~_.
-_D~max_i~ > Stake~min~_ when _o~i~ > 1_.
-
-_Demand = Ops_ so
-_Demand = o * N~stakers~_ +
-_Demand = o * c * (Tokens~total~ / Stake~min~)_.
-
-Let constant factor _f' = c * f~price~_.
-
-Now, _Price = o * f' * N~max_stakers~_.
-
-Also _Stake~actual~ = Stake~min~ * f' * o * Tokens~total~ / Stake~min~_
-simplifying to _o * f' * Tokens~total~_.
-
-Let _f'' = 1 / (f' * Tokens~total~)_.
-
-The ratio _D~max_i~ / Stake~actual~ = o~i~ * Stake~min~ / (o * Stake~min~) * f''_.
-
-We get _(o~i~ / o) * f''_.
-
-Thus the overleveraging of stakes only actually happens, compared to a constant
-value stake, when _o~i~ > o_ which is constrained by the random distribution of
-_o~i~_ around _o_. This would be expected to follow roughly a poisson
-distribution and thus the probability of _o~i~ / o_ being large is quite small
-with large _o_.
-
-Further add to this that the opportunity cost for _S~i~_ is _R * o~i~_.
-
-'''
-
-== Delegation
-
-=== Option 5: Multioperated delegation
-
-==== General requirements:
-1. _owner_ can only have one operator.
-2. _owner_ can stake any amount of tokens between _Stake~min~_ and their stake.
-3. _operator_ can only be _operating_ on behalf of one _owner_.
-4. If an _owner_ tries to delegate to more than one operator, the tx must
-fail.
-5. If an _owner_ tries to delegate a stake to an _operator_ who already has a
-stake, the tx must fail.
-
-==== Basic design
-
-With this scheme, tokens are staked by signing and publishing a staking contract
-("agreement" to distinguish it from on-chain smart contracts) which specifies
-the various details of any individual staking arrangement. This creates a new
-staker identity in respect to those tokens, which can then be used to
-participate in the network.
-
-To improve security, separate roles are created for each aspect of staking. The
-addresses behind these roles can be the same or different, depending on the
-specific arrangement. This lets token-holders utilize cold storage effectively,
-or delegate different aspects to different parties.
-
-owner::
-The address actually holding the tokens
-
-operator::
-An address authorized to use the tokens as stakes for participating in the
-network
-
-beneficiary::
-An address designated to receive any rewards from participation
-
-overseer::
-An address with the authority to audit and authorize contract upgrades
-
-==== Roles
-
-===== Owner
-
-The owner is the ultimate holder of the tokens. Before staking, the owner has
-full control over the tokens, and the tokens are returned to the owner after
-staking has finished. The owner's participation is not required in the
-day-to-day operations of the staker, so cold storage can be accommodated to the
-maximum extent.
-
-The owner address is used to initiate staking and create the staker, and to
-finish staking and reclaim the staked tokens.
-
-===== Operator
-
-The operator handles the everyday operations of the staker without actually
-owning the staked tokens. While this enables third-party delegation without eg.
-making it possible for the operator to simply transfer away tokens, it should be
-noted that a malicious operator can exploit stake slashing to steal or destroy
-tokens and thus the entire staked amount is indeed at stake.
-
-The operator address is used to provide network functionality by participating
-in various protocols. A signature from the operator is also required to initiate
-staking, and the operator can unilaterally finish staking and return the tokens
-to the owner.
-
-===== Beneficiary
-
-The beneficiary collects rewards earned from staking and participating in the
-network. The beneficiary doesn't sign or publish any protocol-relevant transactions,
-but any currency or tokens earned by the staker will be transferred to the
-beneficiary.
-
-===== Overseer
-
-
-
-==== Stake multioperation
-The stake multioperation feature enables performing several operations on the
-same stake at the same time. As the stake is not locked for any particular
-operation then it is possible for the _operator_ to participate in more than one
-parallel operation using the same stake.
-
-==== Basic structure:
-
-* _delegating contract_
- ** _tokens[owner] -> amount_ table
- ** _staking[owner] -> delegation_id_ table
- ** _operating[operator] -> delegation_id_ table
- ** _op_agreement[delegation_id] -> agreement_ table with:
- *** _amount_ of staked tokens
- *** (if atomic alternative is desired:)
- **** _free_tokens_ unallocated to any contract
- **** _locked_tokens[contract_address] -> amount_ table of allocated tokens
- *** _state_ of the staking agreement
- *** _since_ last change
- *** _owner_ of the tokens
- *** _operator_ performing actions
- *** _beneficiary_ receiving rewards
- *** _authorizer_ auditing upgrades
- ** `delegate` method for delegating
- ** `undelegate` method for initiating undelegation
- ** `reclaim` method for finishing undelegation and freeing tokens
- ** `penalize` method for slashing stakes and rewarding tattletales with tokens
- ** `reward` method for paying out currency rewards
- ** (if atomic alternative is desired: `lock` method for assigning tokens to
- contracts)
-
-* _authorization contract_
- ** _authorized[authorizer] -> [contract_address]_ table
- ** _blocked[contract] -> bool_ table of contracts `panic` has been called on
- ** `authorize` method for adding a contract to the caller's authorization list
- ** `panic` method for aborting all operations on a specific contract and
- revoking authorizations
-
-* _functionality contracts_ provide network functions, and may call methods of
-the _delegating contract_ for rewards and punishments (if atomicity is desired,
-these contracts can also call `lock` with the proper authorization)
-
-==== Functionality
-
-===== Delegating a stake:
-
-1. The _owner_ chooses the _staked amount_, and the _operator_, _beneficiary_ and
-_upgrade authorizer_ addresses and creates a _delegation order_ containing this
-information
-
-2. Both the _owner_ and _operator_ sign the _delegation order_
-
-3. The _delegation order_ is published on-chain
-
-4. The contract receives the _delegation order_ and verifies the following (if
-any condition is unfulfilled, processing aborts):
- * `staking[owner] == nil`
- * `operating[operator] == nil`
- * `tokens[owner] >= staked_amount >= minimum_stake`
-
-5. If all conditions are satisfied the contract processes the _delegation order_
-and sets the following:
-
- * `staking_time := current_time`
- * `delegation_id := hash(owner, operator)`
- * `tokens[owner] -= staked_amount`
- * `staking[owner] := delegation_id`
- * `operating[operator] := delegation_id`
- * {blank}
-+
-....
-op_agreement[delegation_id] := {
- amount = staked_amount,
- state = Active,
- since = staking_time,
- owner = owner,
- operator = operator,
- beneficiary = beneficiary,
- authorizer = upgrade_authorizer
-}
-....
-
-6. The _operator_ can now use this stake for operating
-
-(A _n-to-n_ variant can be designed where owners and operators are not tied to a
-single delegation, but an owner can delegate to unlimited operators, an operator
-can operate for unlimited owners, and each _owner, operator_ pair can have
-unlimited delegation agreements between each other.
-
-This would be done by eliminating the `staking[owner]` and `operating[operator]`
-tables, and by setting `delegation_id := hash(owner, operator, staking_time)`.
-With this change, the only limit is that the owner and operator can only
-establish a single delegation agreement in a single block.)
-
-===== Undelegating a stake:
-
-1. The _owner_ or _operator_ chooses to unstake, and creates a
-_undelegation order_ containing the _delegation ID_
-
-2. Either the _owner_ or _operator_ signs the _undelegation order_ and publishes
-it on-chain
-
-3. The contract receives the _undelegation order_ and verifies the following
-(`d_agreement := op_agreements[delegation_id]`):
-
- * `d_agreement != nil`
- * The _undelegation order_ is signed by either `d_agreement.owner` or
- `d_agreement.operator`
-
-4. If the conditions are satisfied, the contract processes the
-_undelegation order_ and sets the following:
-
- * `unstaking_time := current_time`
-
- * `d_agreement.state := Unstaking`
-
- * `d_agreement.since := unstaking_time`
-
-5. The _operator_ can not enter new operations until the undelegated stake is
-reclaimed
-
-===== Claiming undelegated stake
-
-1. After _T~unstake~_ has passed since the _undelegation order_ has been
-processed, the _owner_ or _operator_ creates, signs and publishes a
-_stake reclaiming order_ containing the _delegation ID_
-
-2. The contract receives the _stake reclaiming order_ and verifies the
-following (`d_agreement := op_agreements[delegation_id]`):
-
- * `d_agreement != nil`
- * The _stake reclaiming order_ is signed by either `d_agreement.owner` or
- `d_agreement.operator`
- * `d_agreement.state == Unstaking`
- * `d_agreement.since + unstake_delay =< current_time`
-
-3. The contract processes the _stake reclaiming order_ and sets the following:
-
- * `tokens_unlocked := d_agreement.amount - new_penalties` (`new_penalties`
- applies if eg. an operation is still underway and it has been decided to set
- penalties for reclaiming stakes in such a situation)
- * `staking[owner] := nil`
- * `operating[operator] := nil`
- * `op_agreements[delegation_id] := nil`
- * `tokens[owner] += tokens_unlocked`
-
-4. The _operator_ is now free to start operating for a new _owner_
-
-(In the _n-to-n_ variant the `staking[owner]` and `operating[operator]` tables
-are absent)
-
-===== Operating on a stake
-
-1. When the _operator_ tries to join an operation (eg. present a ticket for beacon
-group selection) they should create a _operation initialization order_ including
-the _delegation ID_ and the _contract address_, signed by the _operator_.
-
-2. The _operation initialization order_ is published along with any other data
-required to join the operation, after which the following should be checked
-(`d_agreement := op_agreements[delegation_id]`:
-
- * `d_agreement != nil`
- * `d_agreement.state == Active`
- * If there is a requirement that the operator be staked before _deadline_, then
-`d_agreement.since =< deadline`
- * The request is signed by `d_agreement.operator`
- * `d_agreement.amount >= minimum_stake`
- * The current contract has been authorized by `d_agreement.authorizer`
- * The current contract has not been blocked with the panic button:
-`blocked[contract_address] == nil`
-
-3. If the checks pass, the operator may join the operations.
-
-===== Rewards
-
-1. If the operator is awarded a _reward_ of currency, the reward should be paid
-to `d_agreement.beneficiary`
-
-===== Penalties
-
-1. If the operator is to be punished by stake slashing, the
-_penalizing contract_ should call the _delegation contract_ with the _penalty_.
-The _penalty_ should contain the following:
-
- * The _penalty amount_
- * The _delegation ID_ to be slashed
- * Optionally the _tattletale reward amount_ and the _tattletale delegation ID_
-
-2. The _delegation contract_ should then check the following
-(`d_agreement := op_agreements[delegation_id]`):
-
- * The _penalizing contract_ is authorized by `d_agreement.authorizer` and has
-not been blocked with the panic button
- * `penalty_amount =< minimum_stake`
-
-3. If the penalty is valid, the _delegation contract_ will then perform the
-following:
-
- * `actual_penalty := min(penalty_amount, d_agreement.amount)`
- * If there is a tattletale reward:
- ** `actual_tattletale_reward := min(tattletale_reward_amount, actual_penalty)`
- ** `tattletale_beneficiary := op_agreements[tattletale_id].beneficiary`
- ** `tokens[tattletale_beneficiary] += actual_tattletale_reward`
- * `d_agreement.amount -= actual_penalty`
- * If `d_agreement.amount < minimum_stake`, then the operator is blocked from
-joining any new operations and the tokens are automatically unstaked:
- ** `d_agreement.state := Unstaking`
- ** `d_agreement.since := current_time`
-
-The _actual penalty_ is set to be at most the amount of tokens remaining in the
-stake, and the _actual tattletale reward_ is set to be at most the
-_actual penalty_ to ensure no new tokens can be created by exploiting
-overstaking. However, this means that it becomes possible to deny the tattletale
-a reward by processing other penalties (where the misbehaving party also
-controls the tattletale, to reduce their losses) first so that there is no stake
-remaining when the real tattletale's turn comes. The only way to avoid this is
-by stake atomicity so each operation is backed by hard tokens.
-
-===== Upgrading a contract
-
-1. The _upgrade authorizer_ audits and authorizes the new contract
-
-2. The _upgrade authorization contract_ checks that the _contract address_ is
-present on the canonical version list, and adds it to the authorizer's list of
-authorized contracts: `upgrade_authorizer.contracts += contract_address`
-
-The rationale for this is that the authorizations can be outsourced to a third
-party, and thus it is useful to have the authorizations stored separately to
-reduce costs compared to including them in each delegation agreement.
-
-If the new contract is found compromised, the recourse is for the _owner_ or
-_operator_ to unstake or for the _panic button_ to be used to halt all
-operations on the compromised contract. Once authorized, a contract is
-technically capable of completely burning or transfering any staked tokens, even
-if unstaking has been ordered. If this were not the case it would be possible to
-avoid legitimate penalties.
-
-Stake atomicity could be used to reduce exposure to compromised contracts, by
-limiting the amount subject to the contract. Stake atomicity can be combined
-with contract-specific stakes while keeping global minimum stake constant, so
-that network throughput can be improved by upgrading contracts to new versions
-with lower stakes required to participate.
diff --git a/docs-v1/random-beacon/dkg/alternative.adoc b/docs-v1/random-beacon/dkg/alternative.adoc
deleted file mode 100644
index b9ad6451be..0000000000
--- a/docs-v1/random-beacon/dkg/alternative.adoc
+++ /dev/null
@@ -1,428 +0,0 @@
-= DKG alternative result submission
-
-_Escalating votes_ was originally chosen as the protocol
-for DKG result submission
-due to its favorable gas costs.
-By reducing the frequency of group creation,
-it is feasible to use _full verification_ instead.
-_Full verification_ costs significantly more gas
-in the expected typical scenario,
-but is also more robust.
-
-With the _full verification_ alternative,
-competing submissions are not presented.
-Instead, the participants agree on a result off-chain, sign it,
-and the first available participant submits the result on-chain
-as soon as eligible.
-
-== Basic description
-Each participant _P~i~_ calculates the result they believe to be correct;
-this is called the _preferred result_ of _P~i~_.
-The participants sign broadcast their _preferred results_.
-Each participant should sign and broadcast one _preferred result_;
-signing more than one _preferred result_ can be proven on-chain
-and will be heavily penalized.
-
-After receiving the _preferred results_ of other participants,
-_P~i~_ counts the signatures on each result.
-The result with at least _H_ signatures is the _quorum result_.
-The _quorum result_ is published on-chain along with its signatures.
-
-The contract checks that the result is correct
-and has at least _H_ valid signatures.
-If the checks pass,
-a new group is successfully created.
-
-== Multiple quorum results
-It is possible that there is more than one _quorum result_.
-This always requires that at least one participant
-has signed two different results.
-Additionally, either the honest majority assumption has been violated
-or the honest participants are split over different results.
-
-There are multiple different ways to deal with this.
-
-[upperalpha]
-. Accept either result
-because under honest majority both must have at least one honest signer
-. Discard signatures from disqualified participants
-and reject all results because no honest quorum was achieved
-. Discard signatures from disqualified participants
-and attempt to reconstruct a valid result,
-aborting only if the results are incompatible
-
-== Option A: accept either
-Option A has a very simple on-chain implementation.
-It is sufficient to accept the first submission
-with at least _H_ signatures
-and reject any further submissions.
-Members who provably sign multiple submissions
-can be removed from the group on the fly.
-
-However, because signing two different results is forbidden,
-neither result has the support of _H_ not-provably-misbehaving participants.
-This would permit an adversary to force the creation of
-a group where the adversary has a linchpin position.
-
-Let the results be _a_ and _b_.
-Let the number of honest participants
-signing each result be _h~a~_ and _h~b~_ respectively.
-Let the malicious participants be _m~a~_ and _m~b~_,
-and _m~ab~_ for those who sign both results.
-Let _ia_ and _dq_ be the number
-of inactive and disqualified participants.
-
-==== No honest majority
-If this attack happens because the honest majority assumption has failed,
-it is dubious whether it matters
-because the adversary has better attacks available.
-If the honest participants number less than _H_,
-the adversary could outnumber them
-by simply not signing the honest participants' preferred result.
-Signing multiple results can be proven on-chain
-and thus heavily penalized.
-In this scenario option A does not seem to meaningfully reduce security.
-
-_h~a~ < H_
-
-_h~b~ = 0_
-
-_h~a~ + m~a~ + m~ab~ >= H_
-
-_m~b~ + m~ab~ >= H_
-
-_ia + dq + m~ab~ =< M~nofail~_
-
-If _m~ab~_ were to instead sign only _b_,
-the adversary could avoid the punishment
-and guarantee that result _b_ is selected.
-
-The adversary can completely control the group formed by _b_,
-while in _a_ the adversary is only guaranteed a linchpin position
-(the ability to prevent entries from being created
-and to deny submitter rewards to other participants)
-unless _m~a~ + m~ab~ >= H_
-(requiring _m~a~, m~b~ > M~nofail~_ thus _h~a~ < M~nofail~_;
-a rather hopeless situation under any option).
-
-==== Split honest majority
-The other alternative is
-that the honest majority is split over different results,
-and the adversary signs results selectively to manipulate the outcome.
-
-_h~a~ + h~b~ >= H_
-
-_m~a~ + m~ab~ + m~b~ =< M_
-
-_h~a~ + m~a~ + m~ab~ >= H_
-
-_h~b~ + m~b~ + m~ab~ >= H_
-
-_ia~a~ + dq~a~ + m~ab~ =< M~nofail~_
-
-_ia~b~ + dq~b~ + m~ab~ =< M~nofail~_
-
-_h~a~ + m~a~ < H_
-
-_h~b~ + m~b~ < H_
-
-If the honest majority is irreconcilably split
-and the results _a_ and _b_ have different _QUAL_
-and thus different group public keys,
-the adversary is able to guarantee itself a linchpin position
-regardless of the winning result.
-
-If the honest majority agrees on _QUAL_ and _Y_,
-the adversary can obtain a linchpin position
-if _a_ sets many participants from _h~b~_ as inactive,
-and vice versa.
-Otherwise the resulting group will be capable of
-producing signatures without contribution from the adversary.
-
-By having _m~ab~_ sign only one of the two results,
-the adversary could choose the more favorable outcome
-and avoid the penalties for signing conflicting results.
-
-=== Option B: reject both
-Option B provides the most robust guarantees
-but is complex to implement on-chain.
-
-It is not enough to accept
-the first result to be signed by at least _H_ members
-because some of those signatures could be invalidated later.
-The first result that appears to meet quorum
-would have to be set as the _tentative result_,
-as it could become invalid as proofs of misbehavior are submitted.
-
-Signatures by each member need to be tracked,
-and members disqualified for multiple signatures
-must be recorded in a special blacklist.
-
-Because an adversary could submit a result with exactly _H_ signatures,
-and afterwards invalidate some of them,
-it is necessary that signatures can be added to the _tentative result_.
-
-A separate finalization after submission time has run out
-would remove disqualified signatures
-and determine whether the _tentative result_ remains valid.
-(No other result could become valid;
-if the _tentative result_ is invalidated
-it is impossible for any result to gain _H_ valid signatures.)
-
-=== Option C: try to reconstruct a valid result
-In option C,
-conflicting results can be reconciled
-to obtain one acceptable outcome.
-Results are not treated as immutable units,
-but rather as sets of votes for each component.
-
-Two or more conflicting results can be reconciled
-if they agree on _Y_ (and implicitly _QUAL_).
-If multiple results with the same _Y~a~_
-have at least _H_ valid signatures across them,
-_Y~a~_ can be considered the true group public key.
-
-_IA_ and _DQ_ could be reconciled thus:
-
-. _P~i~_ is disqualified if at least _H_ valid signatures
-support results where _P~i~_ is disqualified.
-. _P~i~_ is inactive if at least _H_ valid signatures
-support results where _P~i~_ is either inactive or disqualified,
-and _P~i~_ is not disqualified due to the previous clause.
-
-If neither of the above apply,
-_P~i~_ is deemed to be neither disqualified nor inactive.
-(Other solutions could also be just as viable.)
-
-Reconciling conflicting but compatible results
-could reduce the impact
-of honest members splitting across multiple results;
-a disagreement on a single participant's inactivity
-could cause divergence and DKG failure without reconciliation.
-
-However, reconciling results is only useful if the broadcast channel fails,
-and on-chain reconciliation is unnecessarily complex and expensive.
-Reconciling conflicting results would be best performed
-by the participants first broadcasting their _preferred results_,
-then applying reconciliation,
-and finally broadcasting their signatures for the reconciled result.
-
-== Phase 13': Result determination
-In the result determination phase,
-each participant _P~i~_ constructs the canonical representation
-of the result they believe to be correct,
-and prepares to store it:
-
-_P~i~_ calculates the group public key share _Y~j~_
-of each member, including inactive and disqualified ones.
-
-(_This section is not strictly required for early implementations:_
-
-_P~i~_ proceeds to construct a merkle tree of these public key shares;
-the merkle root of this tree is _MerkleRoot~Y~_.
-
-_End section_)
-
-The on-chain representation of the result is formed of:
-
-* a unique identifier of this particular run of the DKG protocol _DkgID_
-* the group public key _Y_
-* the set of inactive members _IA_
-* the set of disqualified members _DQ_
-* (_MerkleRoot~Y~_ if used)
-
-The _inner hash_ of the result is `sha3(Y, MerkleRoot_Y, IA, DQ)`.
-The _outer hash_ is `sha3(DkgID, inner_hash)`.
-
-_P~i~_ then signs the _outer hash_ of this _preferred result_,
-and broadcasts the hash and the signature to other participants.
-Agreement on this hash is sufficient to ensure agreement on the result,
-including each good participant's public key shares.
-
-== Phase 14': Result submission
-_P~i~_ receives the result signature messages from other participants,
-and proceeds to determine the ultimate outcome of the DKG.
-
-The result supported by at least _H_ participants
-is called the _quorum result_.
-If the honest majority assumption holds,
-a _quorum result_ must have been signed by at least one honest participant.
-
-How _P~i~_ should proceed depends on whether a _quorum result_ exists,
-and whether it matches _P~i~_'s _preferred result_:
-
-* If there is no _quorum result_,
-quorum has not been achieved and the DKG ends inconclusively.
-
-* If there is a single _quorum result_
-and it matches the _preferred result_,
-a new group is formed correctly and _P~i~_ is able to participate in it.
-_P~i~_ stores the public key shares _Y~j~_ until the group expires,
-and prepares to submit the result on-chain if needed.
-
-* If there is a single _quorum result_
-that does not match the _preferred result_,
-a new group is formed correctly but _P~i~_ may not be able to participate.
-If the _quorum result_ is _reconcilable_ with the _preferred result_;
-meaning it has the same _Y_ (and _MerkleRoot~Y~_),
-and _P~i~_ is among the ultimately qualified participants;
-_P~i~_ can replace their _preferred result_ with the _quorum result_.
-Otherwise _P~i~_ could not participate without more complex reconciliation.
-
-At this point,
-different solutions for handling multiple quorum results diverge.
-
-=== Option A
-* If there are multiple _quorum results_,
-and one of them matches the _preferred result_,
-_P~i~_ should attempt to submit the _preferred result_.
-
-* If there are multiple _quorum results_,
-none of which matches the _preferred result_,
-but one or more results are _reconcilable_,
-_P~i~_ should wait to see which result is submitted first.
-
-* If there are multiple _quorum results_,
-all _non-reconcilable_,
-_P~i~_ cannot participate further.
-
-If the DKG ends inconclusively,
-no result is submitted on-chain.
-
-If a group is formed correctly and _P~i~_ is able to participate,
-the result is submitted on-chain
-by the first eligible participant able to do so.
-Eligibility to submit the result is calculated as in _Phase 13_.
-The on-chain submission consists of the result
-along with its signatures,
-each accompanied by the member index of the signer.
-
-==== Processing submissions on-chain
-When a result is submitted,
-the contract checks that
-the _DkgID_ of the result matches the DKG execution,
-each signature on the result is valid,
-and at least _H_ signatures are present.
-
-If the checks pass:
-
-* Each inactive (included in the set _IA_ of the _tentative result_),
-disqualified (included in the set _DQ_ of the _tentative result_),
-and _blacklisted_ member
-is removed from the group
-* _Y_ is stored as the group public key
-* (If used, _MerkleRoot~Y~_ is stored
-as the merkle root of the group public key shares)
-* The submitter is rewarded
-* The group is formed successfully
-and can now be selected for producing beacon entries
-
-==== Misbehavior proofs
-If any participant _P~m~_ has signed two or more different results,
-any participant may publish a _misbehavior proof_ on-chain.
-This _misbehavior proof_ contains
-the unique _DkgID_,
-the member index _m_ of the accused _P~m~_,
-two different _signatures_ and the corresponding _inner hashes_.
-The contract reconstructs the _outer hashes_ using the provided _DkgID_
-(to prevent replay attacks),
-and checks the signatures.
-If both signatures are valid,
-_P~m~_ is heavily penalized and removed from the group.
-The submitter of a valid proof
-leading to a removal from the group
-is rewarded _R~dkg_tattletale~_.
-
-_Misbehavior proofs_ can be published at any time
-regardless of eligibility to submit DKG results.
-A valid _misbehavior proof_ on a past DKG
-can be used if the DKG produced a group which is still active,
-and the misbehaving member is still in the group.
-
-=== Option B
-* If there are multiple _quorum results_,
-quorum cannot be reached after invalidating the members
-who signed multiple results,
-so the DKG will end inconclusively
-once the _misbehavior proofs_ are published.
-
-If a group is formed correctly and _P~i~_ is able to participate,
-the result is submitted on-chain
-by the first eligible participant able to do so.
-Eligibility to submit the result is calculated as in _Phase 13_.
-The on-chain submission consists of the result,
-along with its signatures by non-disqualified participants,
-each accompanied by the member index of the signer.
-
-==== Misbehavior proofs
-Misbehavior proofs are created and checked
-as in option A.
-If the proof is valid,
-_P~m~_ is added to the _blacklist_,
-but not penalized or removed from the group immediately.
-The submitter of a valid proof
-leading to a new _blacklist_ entry
-is rewarded _R~dkg_tattletale~_.
-
-==== Processing submissions on-chain
-When a result candidate is submitted,
-the contract checks that
-the _DkgID_ of the result matches the DKG execution,
-each signature on the result is valid,
-and at least _H_ signatures are present.
-If the checks pass,
-the result candidate is designated as the _tentative result_
-and stored along with indices of the signers
-(signatures themselves can be discarded);
-the submitter is recorded as the _result submitter_
-along with the number of signers.
-
-After the _tentative result_ has been determined,
-any participant can add signatures to it
-by submitting one or more signatures
-with the signers' member indices.
-If all submitted signatures are valid,
-the signers' indices are added to the _tentative result_;
-the submitter is recorded as a _result supporter_
-along with the number of new signers
-whose indices were not already included
-in the signers of the _tentative result_.
-
-After a specified time period has elapsed,
-any participant can _finalize_ the DKG.
-Upon finalization:
-
-1. Each member on the _blacklist_ is penalized heavily.
-
-2. If there is no _tentative result_:
-the DKG aborts and the group is not formed.
-The _finalizer_ (the participant making the finalization transaction)
-is paid _R~dkg_inconclusive~_ to cover gas costs.
-
-3. Each member on the _blacklist_ is removed
-from the signers of the _tentative result_, if present.
-
-4. If the number of remaining signers on the _tentative result_
-is less than _H_:
-the DKG aborts and the group is not formed.
-The _finalizer_ is paid _R~dkg_inconclusive~_.
-
-5. If at least _H_ signers are remaining on the _tentative result_:
-** Each inactive (included in the set _IA_ of the _tentative result_),
-disqualified (included in the set _DQ_ of the _tentative result_),
-and _blacklisted_ member
-is removed from the group
-** _Y_ is stored as the group public key
-** (If used, _MerkleRoot~Y~_ is stored
-as the merkle root of the group public key shares)
-** Contributors are rewarded:
-*** The _result submitter_ is paid a constant amount _R~dkg_submit_base~_
-plus _R~dkg_submit_signer~_ per each signer in the original submission
-*** Each _result supporter_ is paid _R~dkg_support_signer~_
-per each new signer they added to the result
-*** The _finalizer_ is paid _R~dkg_finalized~_
-** The group is formed successfully
-and can now be selected for producing beacon entries
-
-=== Option C
-TBD
diff --git a/docs-v1/random-beacon/dkg/concepts.adoc b/docs-v1/random-beacon/dkg/concepts.adoc
deleted file mode 100644
index f3ddf1a1a1..0000000000
--- a/docs-v1/random-beacon/dkg/concepts.adoc
+++ /dev/null
@@ -1,50 +0,0 @@
-= Details+Rationale
-
-== Message delivery
-
-=== Broadcast channel
-
-Every group member in phase _p_ can safely assume
-every non-inactive group member has seen
-all messages broadcast within _T~p~_ after the beginning of phase _p_.
-
-All messages broadcast by _P~i~_ are assumed to be signed with _X~i~_.
-
-A message is malformed if it cannot be parsed and validated
-as the message required in a particular phase of the protocol.
-
-The implementation details of the broadcast channel
-are currently out of scope for this document.
-
-==== Assumptions and implications
-
-The broadcast channel is assumed to give all participants
-the same view of the world,
-and deliver all messages from non-inactive participants
-within a time that is less than the applicable time limit for each phase.
-
-If these assumptions don't hold, certain attacks become possible.
-For example, if a message from _P~i~_
-reaches honest participant _P~j~_ but not _P~k~_,
-their sets of inactive participants _IA~Pj~_ and _IA~Pk~_ will differ.
-This will make them vote for different results,
-which will prevent quorum from being reached on _full signing_,
-while on _escalating votes_ a coordinating adversary
-could make its preferred incorrect result win the vote.
-To protect against the latter,
-_escalating votes_ assumes a null result when any single result is opposed
-by _f~max~ + 1_ participants as it means that the honest votes are split.
-
-== Result format
-
-The result of the DKG protocol can be either a success or a failure.
-
-Success means the DKG protocol finished with at most _M~fail~_ participants
-misbehaving or dropping offline during the execution of the protocol,
-and the group of the remaining honest participants _G_
-should be added to the signing groups for the threshold relay.
-
-Failure means that the group creation could not finish, due to either
-the number of (inactive + disqualified) participants exceeding _M~fail~_,
-or the presented results being disputed
-in a way where the correct outcome cannot be ascertained.
diff --git a/docs-v1/random-beacon/dkg/dkg.py b/docs-v1/random-beacon/dkg/dkg.py
deleted file mode 100644
index f59be4ee64..0000000000
--- a/docs-v1/random-beacon/dkg/dkg.py
+++ /dev/null
@@ -1,397 +0,0 @@
-# i = always the player whose perspective we're in
-
-
-# tag::phase-1[]
-# Because G1 and G2 in alt_bn128 are cyclic groups of prime order, this number
-# can also be used as the size of the secret sharing finite field
-q = G1.curveOrder
-
-# Receive the DKG parameters from on-chain
-dkgSetup = getDkgSetup()
-
-# Presented from the perspective of P_i
-i = dkgSetup.members.index(self.pubkey)
-
-# Keep track of other qualified participants
-#
-# `goodParticipants[P]` denotes the qualified participants in phase `P`
-#
-goodParticipants[1] = [1..N]
-
-# Record the blockheight at the start of the DKG
-#
-# Used later for calculating timeouts
-#
-T_dkgInit = getCurrentBlockHeight()
-
-ephemeralPubkeys = []
-
-for j in goodParticipants[1], j != i:
- x_ij = genEcdhKeypair()
-
- self.ephemeralKey[j] = x_ij
-
- y_ij = x_ij.pubkey
-
- ephemeralPubkeys[j] = y_ij
-
-broadcast(messagePhase1(ephemeralPubkeys))
-# end::phase-1[]
-
-
-# tag::phase-2[]
-# Receive messages from phase 1:
-# - ephemeral public keys of other participants
-# IA if message not received
-#
-# Validate:
-# - message from P_j must contain a public key for all P_k, k != j
-# DQ if public key absent
-# - all public keys must be valid curve points of the ECDH curve
-# DQ if invalid
-#
-messages.receive(1)
-
-for j in goodParticipants[2], j != i:
- privkey_ij = self.ephemeralKey[j]
- pubkey_ji = ephemeralPubkey(j, i)
-
- k_ij = ecdh(privkey_ij, pubkey_ji)
- self.symkey[j] = k_ij
-# end::phase-2[]
-
-
-# tag::phase-3[]
-# GJKR 1.(a):
-# f_i(z) = a_i0 + a_i1 * z + ... + a_it * z^t
-# f'_i(z) = b_i0 + b_i1 * z + ... + b_it * z^t
-#
-# a_ij = sharePolyCoeffs[j]
-# b_ij = blindingFactors[j]
-#
-# G1.randomScalar = integer from range(0, q)
-#
-self.sharePolyCoeffs = [0..M].map(G1.randomScalar)
-self.blindingFactors = [0..M].map(G1.randomScalar)
-
-
-def f_i(z):
- return evaluateAt(z, self.sharePolyCoeffs) % q
-
-
-def g_i(z):
- return evaluateAt(z, self.blindingFactors) % q
-
-
-z_i = self.sharePolyCoeffs[0]
-# assert(z_i == f_i(0))
-
-
-self.commitments = map(ecCommit, self.sharePolyCoeffs, self.blindingFactors)
-
-encryptedShares = []
-
-for j in goodParticipants[3]:
- s_ij = f_i(j)
- t_ij = g_i(j)
-
- if i != j:
- pointsBytes = marshalPoints(s_ij, t_ij)
- payload_ij = encrypt(self.symkey[j], pointsBytes)
-
- encryptedShares[j] = payload_ij
- else:
- self.shares[i] = (s_ij, t_ij)
-
-broadcast(messagePhase3(encryptedShares, self.commitments))
-# end::phase-3[]
-
-
-# tag::phase-4[]
-# Receive messages from phase 3:
-# - commitments to the secret sharing polynomials
-# - encrypted share payloads
-# IA if message not present
-#
-# Validate:
-# - the expected number of commitments (M + 1) is present
-# DQ if n of commitments incorrect
-# - commitments must be valid curve points of G1
-# DQ if a commitment is not valid curve point
-# - message from P_j must contain encrypted payloads for all other participants
-# DQ if payload absent
-# - the length of each payload must be: 2 * G1_SCALAR_LENGTH + MAC_LENGTH
-# DQ if a payload has incorrect length
-#
-messages.receive(3)
-
-shareComplaints = []
-
-for j in goodParticipants[4], j != i:
- k_ij = self.symkey[j]
-
- validShares = decryptAndValidateShares(
- senderIndex = j,
- recipientIndex = i,
- symkey = k_ij
- )
-
- if not validShares:
- X_ij = self.ephemeralKey[j]
- shareComplaints.append(shareComplaint(j, X_ij))
- else:
- (s_ji, t_ji) = validShares
- self.shares[j] = (s_ji, t_ji)
-
-broadcast(messagePhase4(shareComplaints))
-# end::phase-4[]
-
-
-# tag::phase-5[]
-# Receive messages from phase 4:
-# - complaints about inconsistent shares, or "no complaints"
-# IA if not present
-#
-# Validate:
-# - each revealed private key must be a valid scalar for ECDH
-# DQ if invalid
-# - each revealed private key must correspond to the public key
-# DQ if does not match
-# (explicit in pseudocode)
-#
-messages.receive(4)
-
-for complaint in messages[4]:
- j = complaint.senderIndex
- m = complaint.accusedIndex
- privkey_jm = complaint.privkey
-
- # Presented private key does not correspond to the published public key
- #
- # Disqualify accuser
- #
- if not validatePrivkey(
- senderIndex = j,
- recipientIndex = m,
- privkey = privkey_jm
- ):
- disqualify(5, j)
- else:
- pubkey_mj = ephemeralPubkey(m, j)
-
- k_jm = ecdh(privkey_jm, pubkey_mj)
-
- # Check whether the shares are consistent with the accused's commitments
- sharesValid = decryptAndValidateShares(
- senderIndex = m,
- recipientIndex = j,
- symkey = k_jm
- )
-
- # Shares inconsistent, disqualify accused
- if not sharesValid:
- disqualify(5, m)
- # Shares consistent, disqualify accuser
- else:
- disqualify(5, j)
-# end::phase-5[]
-
-
-# tag::phase-6[]
-# GJKR 2:
-#
-QUAL = goodParticipants[6]
-
-# GJKR 3:
-#
-# x_i = sum([ s_ji for j in QUAL ]) % q
-# x'_i = sum([ t_ji for j in QUAL ]) % q
-#
-# This is safe to calculate here as the consistency of the shares has been
-# ascertained. If a participant gets disqualified later their public key piece
-# will be reconstructed to match the honest participants' shares.
-#
-x_i = sum(
- [ self.shares[j].share_S for j in QUAL ]
-) % q
-
-xprime_i = sum(
- [ self.shares[j].share_T for j in QUAL ]
-) % q
-# end::phase-6[]
-
-
-# tag::phase-7[]
-# GJKR 4.(a):
-#
-# A_ik = g^a_ik % p
-#
-self.pubkeyCoeffs = [
- P1.scalarMult(A_ik) for A_ik in self.sharePolyCoeffs
-]
-
-broadcast(messagePhase7(self.pubkeyCoeffs))
-# end::phase-7[]
-
-
-# tag::phase-8[]
-# Receive messages from phase 7:
-# - public key coefficients
-# IA if message not present
-#
-# Validate:
-# - the expected number (M + 1) of pubkey coefficients must be present
-# DQ if incorrect number of coeffs
-# - public key coefficients must be valid curve points for G1
-# DQ if a coefficient is not a valid curve point
-#
-messages.receive(7)
-
-pubkeyComplaints = []
-
-for j in goodParticipants[8]:
- pubkeyShareValid = validatePubkeyCoeffs(
- senderIndex = j,
- recipientIndex = i,
- share_S = self.shares[j].share_S
- )
-
- if not pubkeyShareValid:
- pubkeyComplaints.append(pubkeyComplaint(j))
-
-broadcast(messagePhase8(pubkeyComplaints))
-# end::phase-8[]
-
-
-# tag::phase-9[]
-# Receive messages from phase 8:
-# - complaints about invalid public key coefficients, or "no complaints"
-# IA if no message sent
-#
-# Validate:
-# - each revealed private key must be a valid scalar for ECDH
-# DQ if invalid
-# - each revealed private key must correspond to the public key
-# DQ if does not match pubkey from phase 1
-# (explicit in pseudocode)
-#
-messages.receive(8)
-
-for complaint in messages[8]:
- j = complaint.senderIndex
- m = complaint.accusedIndex
- privkey_jm = complaint.privkey
-
- if not validatePrivkey(
- senderIndex = j,
- recipientIndex = m,
- privkey = privkey_jm
- ):
- disqualify(9, j)
- else:
- pubkey_mj = ephemeralPubkey(m, j)
-
- symkey = ecdh(privkey_jm, pubkey_mj)
-
- badActor = resolvePubkeyComplaint(
- senderIndex = m,
- recipientIndex = j,
- symkey = symkey
- )
-
- if badActor == "accused" or badActor == "both":
- disqualify(9, m)
- if badActor == "complainer" or badActor == "both":
- disqualify(9, j)
-# end::phase-9[]
-
-
-# tag::phase-10[]
-disqualifiedKeys = []
-
-for m in disqualifiedInPhase[9]:
- keyPackage = (m, self.ephemeralKey[m])
- disqualifiedKeys.append(keyPackage)
-
-broadcast(messagePhase10(disqualifiedKeys))
-# end::phase-10[]
-
-
-# tag::phase-11[]
-# Receive messages from phase 10:
-# - good participants' ephemeral private keys for each disqualified participant
-# IA if no message sent
-#
-# Validate:
-# - all expected private keys are revealed
-# DQ if number of keys is incorrect
-# - each revealed private key must be a valid scalar for ECDH
-# DQ if a private key is invalid
-# - each revealed private key must correspond to the public key
-# DQ if private key does not match public key from phase 1
-# (explicit in pseudocode)
-#
-messages.receive(10)
-
-for keys_j in messages[10]:
- j = keys_j.sender
- for keyPackage in keys_j.keyPackages:
- m = keyPackage.index
- privkey_jm = keyPackage.ephemeralKey
-
- if not disqualifiedInPhase[9].contains(m):
- # P_j broadcast the wrong keys
- disqualify(11, j)
-
- if not validatePrivkey(
- senderIndex = j,
- recipientIndex = m,
- privkey = privkey_jm
- ):
- # P_j broadcast invalid keys
- disqualify(11, j)
- else:
- pubkey_mj = ephemeralPubkey(m, j)
- symkey_jm = ecdh(privkey_jm, pubkey_mj)
-
- validShares = decryptAndValidateShares(
- senderIndex = m,
- recipientIndex = j,
- symkey = symkey_jm
- )
-
- if not validShares:
- # P_j failed to complain earlier
- disqualify(11, j)
- else:
- (s_mj, t_mj) = validShares
- self.revealedShares[m][j] = (s_mj, t_mj)
-
-for m in disqualifiedInPhase[9]:
- shares_m = self.revealedShares[m].values
- indices_m = self.revealedShares[m].indices
-
- z_m = reconstruct(shares_m, indices_m)
- y_m = P1.scalarMult(z_m)
- self.reconstructed_Y_[m] = y_m
-# end::phase-11[]
-
-
-# tag::phase-12[]
-# GJKR 4.(c):
-#
-# Y = product([ A_i0 for i in QUAL ]) % p
-#
-def A_(i):
- if not disqualifiedInPhase[9].contains(i):
- return pubkeyCoeffs(i)
- else:
- return [self.reconstructed_Y_[i]]
-
-Y = ecSum(
- [ A_(i)[0] for i in QUAL ]
-)
-
-for j in goodParticipants[12]:
- self.peerPublicKeys[j] = individualPublicKey(j, QUAL)
-# end::phase-12[]
diff --git a/docs-v1/random-beacon/dkg/dkg_bls.py b/docs-v1/random-beacon/dkg/dkg_bls.py
deleted file mode 100644
index bbc7a4d562..0000000000
--- a/docs-v1/random-beacon/dkg/dkg_bls.py
+++ /dev/null
@@ -1,240 +0,0 @@
-BitArray = List[bool]
-StakerSignature = Tuple[Staker, BlsSignature]
-
-BlockHeight = NewType('BlockHeight', int)
-
-class CandidateGroup(NamedTuple):
- members: List[Staker]
- createdAt: Blockheight
- minH: int # minimum number of honest parties required
- maxM: int # maximum number of misbehaving parties before failure
-
-
-class Staker(NamedTuple):
- ecdsaPubkey: EcdsaPubkey
- blsPubkey: BlsPubkey
- stakedTokens: TokenAmount
-
-
-class Result(NamedTuple):
- groupPubkey: Optional[BeaconPubkey]
- disqualified: Optional[BitArray]
- inactive: Optional[BitArray]
-
-
-class SignedResult(NamedTuple):
- result: Result
- signature: BlsSignature
-
-
-class ResultSubmission(NamedTuple):
- result: Result
- signature: BlsSignature
- signers: BitArray
-
-
-def Failure(disqualified = None):
- return Result(False, disqualified, None)
-
-
-def Success(pubkey, disqualified, inactive):
- return Result(pubkey, disqualified, inactive)
-
-
-def isFailure(result):
- return result.pubkey == False
-
-
-def isSuccess(result):
- return result.pubkey != False
-
-
-# Bn256 interface:
-
-# -- functions applying to each of G1 and G2:
-# class CurvePoint gx where
-# generator :: gx
-# asPoint :: Bytes -> gx
-# ecmul :: gx -> Scalar -> gx
-# ecadd :: gx -> gx -> gx
-# instance CurvePoint G1
-# instance CurvePoint G2
-
-# -- calculate the pairing of two curve points
-# pairing :: G1 -> G2 -> GT
-
-
-BlsPrivkey = Bn256.Scalar
-BlsPubkey = Bn256.G2
-BlsSignature = Bn256.G1
-
-
-def blsPubkey(
- privkey: BlsPrivkey
-) -> BlsPubkey:
- return Bn256.ecmul(Bn256.generator, privkey)
-
-
-def blsSign(
- message: Bytes,
- privkey: BlsPrivkey
-) -> BlsSignature:
- h = Bn256.asPoint(sha3(message))
- return Bn256.ecmul(h, privkey)
-
-
-def blsVerify(
- signature: BlsSignature,
- message: Bytes,
- pubkey: BlsPubkey
-) -> bool:
- h = Bn256.asPoint(sha3(message))
- sigPairing = Bn256.pairing(signature, Bn256.generator)
- keyPairing = Bn256.pairing(h, pubkey)
- return sigPairing == keyPairing
-
-
-def blsCombinePubkeys(
- pubkeys: List[BlsPubkey]
-) -> BlsPubkey:
- return reduce(Bn256.ecadd, pubkeys)
-
-
-def getResult(
- signedResults: Dict[Staker, SignedResult],
- groupInfo: CandidateGroup
-) -> Optional[ResultSubmission]:
-
- # for each result, list its supporters and their signatures
- preferredResults: Dict[Result, StakerSignature] = {}
-
- for (staker, signedResult) in signedResults:
- result = signedResult.result
- signature = signedResult.signature
-
- if result in preferredResults:
- preferredResults[result].append((staker, signature))
- else:
- preferredResults[result] = [(staker, signature)]
-
- # for each result, counts how many members support it
- orderedResults: Dict[Result int] = {}
-
- for (result, supporters) in preferredResults:
- orderedResults[result] = len(supporters)
-
- leadingResult = keyByMaxValue(orderedResults)
-
- participantPlurality = preferredResults[leadingResult]
-
- if len(participantPlurality) < groupInfo.minH:
- return None
- else:
- participants = groupInfo.members
-
- # set up the bit array showing who signed the result
- submissionSigners = [False] * len(participants)
-
- submissionSignatures = []
-
- # for each supporter of the plurality resul, set their index in the
- # signers array to True and add their signature to the group signature
- for (signer, signature) in participantPlurality:
- submissionSigners[participants.index(signer)] = True
- submissionSignatures.append(signature)
-
- groupSignature = reduce(Bn256.ecadd, submissionSignatures)
-
- return ResultSubmission(
- leadingResult,
- groupSignature,
- submissionSigners
- )
-
-
-def validate(
- submission: ResultSubmission,
- candidateGroup: CandidateGroup
-) -> bool:
-
- # a group signature for the result
- signature = submission.signature
-
- # A one-indexed array whose length is N,
- # signers[i] = does the group signature include
- # the signature of the i-th member
- signers = submission.signers
-
- result = submission.result
-
- # require at least the honest majority number of signers
- signersRequired = candidateGroup.minH
- participants = candidateGroup.members
-
- # too few signatures?
- if signers.count(True) < signersRequired:
- return False
- else:
- # roll together the pubkeys of those who have signed the result
- signerPubkeys = []
- for s in signers, p in participants:
- if s == True:
- signerPubkeys.append(p.blsPubkey)
- creationPubkey = reduce(Bn256.ecadd, signerPubkeys)
-
- return blsVerify(
- signature,
- result,
- creationPubkey
- )
-
-
-def isEligible(
- sender: Staker,
- t_diff: BlockHeight,
- participants: List[Staker]
-) -> bool:
- i = participants.index(sender)
- maxEligible = 1 + max(0, (t_diff - t_dkg) / t_step)
-
- return i <= maxEligible
-
-
-def receiveResult(
- candidateGroup: CandidateGroup
-) -> Result:
- finalized = False
- validResult = False
-
- t_init = candidateGroup.createdAt
-
- while not finalized:
- t_now = currentBlockHeight()
- t_diff = BlockHeight(t_now - t_init)
-
- # has the timeout been reached?
- if t_diff > t_timeout:
- finalized = True
- else:
- # get latest submission
- (submission, sender) = latestSubmission()
-
- eligible = isEligible(sender, t_diff, candidateGroup.members)
-
- valid = validate(submission, candidateGroup)
-
- if eligible and valid:
- validResult = submission.result
-
- # rewardSubmitter :: Staker -> CandidateGroup -> IO ()
- # -- give the submitter a reward and penalize everyone whose
- # -- index is smaller than the submitter's for being late
- rewardSubmitter(sender, candidateGroup)
-
- finalized = True
-
- # if no valid result received -> no fault failure
- if not validResult:
- return Failure()
- else:
- return validResult
diff --git a/docs-v1/random-beacon/dkg/dkg_util.py b/docs-v1/random-beacon/dkg/dkg_util.py
deleted file mode 100644
index 03df0ff7ed..0000000000
--- a/docs-v1/random-beacon/dkg/dkg_util.py
+++ /dev/null
@@ -1,235 +0,0 @@
-# i is generic and doesn't relate to perspective
-
-
-# tag::phase-2[]
-# Fetch the correct ephemeral pubkey from messages broadcast in phase 1
-#
-# The format for the message of `P_j` in phase `P` is: `messages[P][j]`
-#
-def ephemeralPubkey(senderIndex, recipientIndex):
- return messages[1][senderIndex].pubkey[recipientIndex]
-# end::phase-2[]
-
-
-# tag::phase-3[]
-# Evaluate a polynomial given by `coeffs` at point `z`
-#
-# `coeffs` is little-endian; `ax^2 + bx + c` is expressed as `[c, b, a]`
-#
-# `evaluateAt(2, [6, 3, 4]) = 6 + (3 * 2^1) + (4 * 2^2) = 28`
-#
-def evaluateAt(z, coeffs):
- return sum(
- [ coeffs[k] * z^k for k in [0..M] ]
- )
-
-
-# Pedersen commitment to secret value `s` and blinding factor `t`
-# `G = P1` is the standard generator of the elliptic curve
-# `H = G*a` is a custom generator where `a` is unknown
-#
-# C(s, t) = G*s + H*t
-#
-def ecCommit(s, t):
- Gs = P1.scalarMult(s)
- Ht = H.scalarMult(t)
- return ecAdd(Gs, Ht)
-# end::phase-3[]
-
-
-# tag::phase-4[]
-# Calculate the sum of a list of elliptic curve points
-def ecSum(points):
- return reduce(ecAdd, points)
-
-
-# Fetch the correct encrypted shares from messages broadcast in phase 3
-def encryptedShares(senderIndex, recipientIndex):
- return messages[3][senderIndex].encryptedShares[recipientIndex]
-
-
-# Fetch a specific participant's commitments from messages broadcast in phase 3
-def commitments(senderIndex):
- return messages[3][senderIndex].commitments
-
-
-# Fetch the correct shares and try to decrypt them with the provided key
-def decryptShares(
- senderIndex,
- recipientIndex,
- symkey
-):
- payload = encryptedShares(senderIndex, recipientIndex)
-
- return decrypt(payload, symkey)
-
-
-# Fetch the shares and validate them
-#
-# Check that shares decrypt correctly and are consistent with the sender's
-# published commitments
-#
-def decryptAndValidateShares(
- senderIndex,
- recipientIndex,
- symkey
-):
- plaintext = decryptShares(
- senderIndex,
- recipientIndex,
- symkey
- )
-
- if not plaintext:
- return False
- else:
- (share_S, share_T) = unmarshalPoints(plaintext)
-
- sharesValid = checkShareConsistency(
- senderIndex,
- recipientIndex,
- share_S,
- share_T
- )
-
- if sharesValid:
- return (share_S, share_T)
- else:
- return False
-
-
-# Check that equation 2 from GJKR holds for `share_S, share_T`
-#
-# P_i is the player whose shares are validated
-# P_j is the perspective player performing the validation
-#
-# GJKR 1.(b):
-#
-# g^s_ij * h^t_ij == product([ C_ik ^ (j^k) for k in [0..T] ]) % p
-#
-def checkShareConsistency(
- recipientIndex,
- senderIndex,
- share_S,
- share_T
-):
- i = senderIndex
- j = recipientIndex
-
- C_i = commitments(i)
-
- C_ecSum = ecSum(
- [ C_i[k].scalarMult(j^k) for k in [0..M] ]
- )
-
- sharesValid = ecCommit(share_S, share_T) == C_ecSum
- return sharesValid
-# end::phase-4[]
-
-
-# tag::phase-5[]
-# Check that a revealed private key matches previously broadcast public key
-def validatePrivkey(senderIndex, recipientIndex, privkey):
- expectedPubkey = ephemeralPubkey(senderIndex, recipientIndex)
- return derivePubkey(privkey) == expectedPubkey
-# end::phase-5[]
-
-
-# tag::phase-8[]
-# Fetch the sender's public key coeffs `A_ik` from messages broadcast in phase 7
-def pubkeyCoeffs(senderIndex):
- return messages[7][senderIndex].pubkeyCoeffs
-
-
-# P_i is the player whose public key share is calculated
-# P_j is the perspective player
-#
-def pubkeyShare(senderIndex, recipientIndex):
- i = senderIndex
- j = recipientIndex
-
- A_i = pubkeyCoeffs(i)
-
- pubkeyShare = ecSum(
- [ A_i[k].scalarMult(j^k) for k in [0..M] ]
- )
- return pubkeyShare
-
-
-# Check that equation 3 holds for `share_S`
-#
-# GJKR 4.(b):
-#
-# g^s_ij == product([ A_ik ^ (j^k) for k in [0..T] ]) % p
-#
-def validatePubkeyCoeffs(
- senderIndex,
- recipientIndex,
- share_S
-):
- return P1.scalarMult(share_S) == pubkeyShare(senderIndex, recipientIndex)
-# end::phase-8[]
-
-
-# tag::phase-9[]
-# Check which party is at fault when a complaint is presented in phase 8
-#
-# Decrypt the shares the accused sent to the complainer in phase 3 and check
-# the validity of the accused's `A_ik` values
-#
-def resolvePubkeyComplaint(
- senderIndex,
- recipientIndex,
- symkey
-):
- plaintext = decryptShares(
- senderIndex,
- recipientIndex,
- symkey
- )
-
- if not plaintext:
- # only happens if the complainer failed to complain earlier
- # and thus both violated protocol
- return "both"
- else:
- (share_S, _) = unmarshalPoints(plaintext)
-
- pubkeyValid = validatePubkeyCoeffs(
- senderIndex,
- recipientIndex,
- share_S
- )
-
- if pubkeyValid:
- return "complainer"
- else:
- return "accused"
-# end::phase-9[]
-
-
-# tag::phase-11[]
-def reconstruct(shares, indices):
- secret = sum(
- [ share_k * lagrange(k, indices) for share_k in shares, k in indices ]
- )
- return secret % q
-# end::phase-11[]
-
-
-# tag::phase-12[]
-# Calculate the individual public key of a specific participant
-#
-# P_i is each qualified participant in turn
-#
-# GJKR (C1'):
-#
-# g^x_j
-# = g^( sum([ s_ij for i in QUAL ]) ) % p
-# = product([ g^s_ij for i in QUAL ]) % p
-# = product([ product([ A_ik ^ (j^k) for k in [0..T] ]) for i in QUAL ]) % p
-#
-def individualPublicKey(memberIndex, QUAL):
- pubkeyShares = [ pubkeyShare(i, memberIndex) for i in QUAL ]
- return ecSum(pubkeyShares)
-# end::phase-12[]
diff --git a/docs-v1/random-beacon/dkg/index.adoc b/docs-v1/random-beacon/dkg/index.adoc
deleted file mode 100644
index ba3bdc0dd4..0000000000
--- a/docs-v1/random-beacon/dkg/index.adoc
+++ /dev/null
@@ -1,428 +0,0 @@
-:toc: macro
-
-= Random Beacon Distributed Key Generation
-
-:toclevels: 4
-
-This proposal for Distributed Key Generation for the threshold relay
-is based on a protocol by Gennaro, Jarecki, Krawczyk and Rabin <>.
-GJKR is further based on Pedersen-VSS (verifiable secret sharing) <>.
-For this implementation, GJKR has been modified
-to make protocol violations objectively attributable
-and remove the need for one-to-one messaging channels.
-
-The protocol uses ephemeral ECDH keys
-to encrypt one-to-one communication on the broadcast channel.
-This ensures that participants can neither
-make baseless complaints nor
-cause a minor nuisance with subtle misbehavior.
-
-Additionally, the threshold relay public key submission protocol
-is defined.
-
-ifndef::yellowpaper[toc::[]]
-
-:leveloffset: +1
-
-include::terms.adoc[]
-
-include::concepts.adoc[]
-
-:leveloffset: -1
-
-
-== Overview
-
-Input: _V~i~, S_
-
-Output: one of
-
-* Successfully generated group _P_ including
-** public key _Y_ of _P_
-** lists of absent and disqualified nodes _IA_ and _DQ_
-* Failure to generate a valid group including
-** list of disqualified nodes _DQ_
-
-The group generation protocol selects a new candidate group _P_ from _S_
-and runs a distributed key generation (DKG) protocol
-to create a threshold signature public key _Y_ for the group,
-to be used in the random beacon.
-
-After a successful execution of the protocol,
-_P_ will be the group of nodes
-that may participate in the random beacon signing,
-having been neither inactive or misbehaving during the DKG.
-
-Inactive nodes will be removed from _P_
-and not be eligible for the rewards
-from participating in the random beacon
-by contributing to the signature _V~j~_
-should _P_ be chosen as the group to produce
-the __j__th random number from the beacon.
-
-Disqualified nodes will be removed from _P_
-and their stake will be slashed in punishment
-for provably and attributably acting in breach of the DKG protocol.
-
-== Protocol
-
-Phases are seen from the perspective of _P~i~_
-
-After phase _p_, the nodes that failed to broadcast a required message
-will be added to _IA~p~_.
-Nodes that broadcast a malformed message may be added to _IA~p~_ or _DQ~p~_.
-
-[#phase-1,reftext="Phase 1"]
-=== Phase 1. Ephemeral key generation
-
-To ensure integrity in later parts of the DKG protocol,
-we will require every _P~i~_ to generate
-an ephemeral ECDH keypair _(x~ij~, y~ij~)_ for every other member _P~j~_ in _P_.
-These will be broadcast in phase 1.
-
-Registering the ephemeral keys on-chain is not required
-if the broadcast channel assumption holds,
-and all honest participants agree on the keys
-published by each participant in phase 1.
-
-.Phase 1
-[source, python]
-----
-include::dkg.py[tags=phase-1]
-----
-
-[#phase-2,reftext="Phase 2"]
-=== Phase 2. Ephemeral ECDH
-
-Every node in _P_ has now published a valid list of ephemeral ECDH pubkeys.
-_P~i~_ will perform ECDH with every _P~j~_ in _P_ to create _k~ij~_.
-
-.Phase 2
-[source, python]
-----
-include::dkg.py[tags=phase-2]
-----
-
-.Utility functions
-[source, python]
-----
-include::dkg_util.py[tags=phase-2]
-----
-
-[#phase-3,reftext="Phase 3"]
-=== Phase 3. Polynomial generation
-
-Every node in _G~3~_ has, for every other node in _G~3~_, a symmetric key that
-can be used for encrypted and attributable communications over the broadcast
-channel. The Pedersen-VSS phase of the GJKR DKG algorithm can commence.
-
-Create two polynomials _f~i~(z)_ and _g~i~(z)_ of degree _M_ and calculate
-other players' shares as points on these polynomials. Additionally, calculate
-Pedersen commitments to the coefficients of _f~i~(z)_ using the coefficients
-of _g~i~(z)_.
-
-Shares to _P~j~_ are encrypted with the symmetric key _K~ij~ = K~ji~_
-shared by _P~i~_ and _P~j~_.
-Commitments and encrypted shares are broadcast to other players.
-
-.Phase 3
-[source, python]
-----
-include::dkg.py[tags=phase-3]
-----
-
-.Utility functions
-[source, python]
-----
-include::dkg_util.py[tags=phase-3]
-----
-
-[#phase-4,reftext="Phase 4"]
-=== Phase 4: Share verification
-
-
-Receive, decrypt and validate shares from other participants. If any share
-proves inconsistent with the sender's published commitments, broadcast a
-complaint by publishing the identity of the misbehaving party along with the
-corresponding ephemeral private key so others can check the result.
-
-.Phase 4
-[source, python]
-----
-include::dkg.py[tags=phase-4]
-----
-
-.Utility functions
-[source, python]
-----
-include::dkg_util.py[tags=phase-4]
-----
-
-[#phase-5,reftext="Phase 5"]
-=== Phase 5: Share complaint resolution
-
-If anyone has complaints about another player, use the published private keys
-to decrypt transmitted messages and determine fault.
-
-As every message in the broadcast channel is signed, decrypting previous
-messages makes misbehavior attributable. For every complaint, one party will be
-disqualified: either the accused sent invalid shares, or the accuser made a
-false complaint.
-
-.Phase 5
-[source, python]
-----
-include::dkg.py[tags=phase-5]
-----
-
-.Utility functions
-[source, python]
-----
-include::dkg_util.py[tags=phase-5]
-----
-
-[#phase-6,reftext="Phase 6"]
-=== Phase 6: Share calculation
-
-Each player sets their share _x~i~_ of the secret _X_ to equal the sum of all
-shares _s~ji~_ as per GJKR. _X_ equals the sum of shares _s~j0~_.
-
-.Phase 6
-[source, python]
-----
-include::dkg.py[tags=phase-6]
-----
-
-[#phase-7,reftext="Phase 7"]
-=== Phase 7: Public key share points
-
-Each player broadcasts their _A~ik~_ values.
-
-.Phase 7
-[source, python]
-----
-include::dkg.py[tags=phase-7]
-----
-
-[#phase-8,reftext="Phase 8"]
-=== Phase 8: Public key share validation
-
-Each player validates the values received in <>.
-
-.Phase 8
-[source, python]
-----
-include::dkg.py[tags=phase-8]
-----
-
-.Utility functions
-[source, python]
-----
-include::dkg_util.py[tags=phase-8]
-----
-
-[#phase-9,reftext="Phase 9"]
-=== Phase 9: Second complaint resolution
-
-As in <>, but with the validation formula from <>.
-
-It should be noted that the symmetric nature of the encryption allows the
-parties to also decrypt _E~jm~_ and not just _E~mj~_. However, this is not very
-significant as even the publication of only the misbehaving participants' shares
-would reduce the security margin excessively if a large fraction of _P_ were to
-misbehave.
-
-By aborting group creation if the number of inactive and disqualified
-participants exceeds _M~nofail~ = M/2_ the impact of this is reduced to a
-manageable level.
-
-.Phase 9
-[source, python]
-----
-include::dkg.py[tags=phase-9]
-----
-
-.Utility functions
-[source, python]
-----
-include::dkg_util.py[tags=phase-9]
-----
-
-[#phase-10,reftext="Phase 10"]
-=== Phase 10: Disqualified share opening
-
-All active players in _G~10~_ broadcast the keys they share with
-players in _DQ~9~_, so the reconstruction of Pedersen-VSS can be done
-offline.
-
-.Phase 10
-[source, python]
-----
-include::dkg.py[tags=phase-10]
-----
-
-[#phase-11,reftext="Phase 11"]
-=== Phase 11: Disqualified share reconstruction
-
-Decrypt and reconstruct _z~m~_ for every participant _P~m~_ that presented
-valid shares in <> but whose public key shares in <> were invalid.
-Calculate _y~m~ = z~m~ * P1_ for each reconstructed _z~m~_.
-
-.Phase 11
-[source, python]
-----
-include::dkg.py[tags=phase-11]
-----
-
-.Utility functions
-[source, python]
-----
-include::dkg_util.py[tags=phase-11]
-----
-
-[#phase-12,reftext="Phase 12"]
-=== Phase 12: Public key reconstruction
-
-Let _G~12~ = G~11~_
-
-Combine _y~j~_ for all participants in _G~6~_ to reconstruct the public key for
-the group. Additionally, calculate and store each qualified participant's
-individual public key for validating signature shares.
-
-.Phase 12
-[source, python]
-----
-include::dkg.py[tags=phase-12]
-----
-
-.Utility functions
-[source, python]
-----
-include::dkg_util.py[tags=phase-12]
-----
-
-[#phase-13,reftext="Phase 13"]
-=== Phase 13: Result establishment
-
-Let _IA = IA~1~ + IA~2~ + ... + IA~10~_
-
-Let _DQ = DQ~1~ + DQ~2~ + ... + DQ~10~_
-
-[source, python]
-----
-if nPlayers(IA + DQ) {lt}= M_nofail:
- correctResult = Result.success(pubkey = Y, inactive = IA, disqualified = DQ)
-
-resultHash = hash(correctResult)
-----
-
-Once the result has been determined,
-all participants evaluate the hash of their preferred result,
-sign the hash and broadcast the hash and a signature over it
-in the group broadcast channel.
-Each participant collects the signatures matching their preferred result,
-stores them along with the signers' member indices.
-
-- If the signature of hash broadcasted off-chain is invalid,
-it will be rejected and not published to the chain in the next phase.
-
-- If multiple signatures from the same member on the same result are found,
-they will all be filtered-out
-so that none of them is published to the chain in the next phase.
-
-If multiple signatures from the same member on different results are found,
-they should all be filtered-out
-so that none of them is published to the chain in the next phase.
-
-If the result for the DKG is a failure
-due to too many members being inactive or disqualified,
-no result is submitted on-chain;
-instead, the DKG is allowed to simply time out.
-
-[#phase-14,reftext="Phase 14"]
-=== Phase 14: Result submission
-
-==== Off-chain
-When a participant becomes eligible to submit the result
-(with supporting signatures) on-chain
-they submit if they have at least the honest majority
-(marked as `H` - constant for the given group size)
-of signatures for that result (including their own).
-
-_First player_ is always eligible to submit the result.
-
-_Second player_ becomes eligible after initial timeout
-(time necessary to perform DKG protocol plus step time `T_dkg + T_step`)
-and remains eligible until the result is accepted by the chain.
-
-In other words, _Nth player_ becomes eligible to submit the result
-after `T_dkg + (N-1) * T_step`
-and remains eligible until the result is accepted by the chain.
-
-If _first player_ is late and _second player_ tries to submit,
-whichever gets mined first wins
-and subsequent submissions are disregarded immediately
-to avoid burdening the loser with excess gas fees.
-
-[source, python]
-----
-alreadySubmitted = False
-resultPublished = False
-finished = False
-
-while not resultPublished:
- T_now = getCurrentBlockHeight()
-
- # using T_init from phase 1
- T_elapsed = T_now - T_init
-
- # determine highest index j eligible to submit
- if T_elapsed <= T_dkg:
- j = 1
- else:
- T_over = T_elapsed - T_dkg
- j = 1 + ceiling(T_over / T_step)
-
- if j >= i:
- broadcast(correctResult)
- resultPublished = True
- alreadySubmitted = True
- else:
- resultPublished = checkChainForResult()
-----
-
-==== On-chain
-When the result is submitted on-chain along with the signatures,
-the contract checks that there are at least `H` signatures or more,
-and that each signature is valid for the submitted result
-and the corresponding member ID.
-Submissions containing multiple signatures
-on the same result from the same member are rejected.
-
-If the above checks pass,
-the result is considered canonical for the group.
-All other group members should abort publishing their results
-and no new result submissions will be accepted by the chain.
-
-If the above checks do not pass, the result is rejected.
-
-If no canonical result has been published until `T_dkg + N * T_step`,
-where `N` is the group size,
-DKG operation is marked as failed.
-
-[bibliography]
-== References
-
-- [[[GJKR]]] Gennaro R., Jarecki S., Krawczyk H., Rabin T. (1999)
-Secure Distributed Key Generation for Discrete-Log Based Cryptosystems.
-In: Stern J. (eds) Advances in Cryptology — EUROCRYPT ’99. EUROCRYPT 1999.
-Lecture Notes in Computer Science, vol 1592. Springer, Berlin, Heidelberg
-
-- [[[Ped]]] Pedersen T.P. (1992)
-Non-Interactive and Information-Theoretic Secure Verifiable Secret Sharing.
-In: Feigenbaum J. (eds) Advances in Cryptology — CRYPTO ’91. CRYPTO 1991.
-Lecture Notes in Computer Science, vol 576. Springer, Berlin, Heidelberg
-
-- [[[EIP-197]]]
-EIP 197: Precompiled contracts for optimal ate pairing check on the elliptic
-curve alt_bn128
diff --git a/docs-v1/random-beacon/dkg/notes.adoc b/docs-v1/random-beacon/dkg/notes.adoc
deleted file mode 100644
index b75d241fb5..0000000000
--- a/docs-v1/random-beacon/dkg/notes.adoc
+++ /dev/null
@@ -1,257 +0,0 @@
-= DKG: notes
-
-== Result format
-
-data Result = NoFaultFailure
- | FailureDQ { disqualified :: Array Bool }
- | PerfectSuccess { pubkey :: BeaconPubkey }
- | SuccessIA { pubkey :: BeaconPubkey
- , inactive :: Array Bool }
- | SuccessDQ { pubkey :: BeaconPubkey
- , disqualified :: Array Bool }
- | MixedSuccess { pubkey :: BeaconPubkey
- , inactive :: Array Bool
- , disqualified :: Array Bool }
-----
-
-For a reasonably compact representation,
-we can use the first byte of the result to encode not only success/failure,
-but also whether there were inactive or disqualified participants.
-
-The inactive and disqualified participants are listed
-in one-indexed bit arrays where the __i__th bit being set means
-_P~i~_ is in the corresponding set.
-
-WARNING: One-indexing is a risk factor for off-by-one errors in the code.
-Using zero-indexed arrays with the first bit unset
-would instead move the risk into the length calculations.
-
-If the __i__th bit is set in both `inactive` and `disqualified`,
-the result message can either be deemed invalid
-or have disqualification take precedence.
-
-The maximum length of a result message is _1 + |BeaconPubkey| + n/4_ bytes.
-
-(For an unreasonably compact representation we could use ternary in trees
-to represent only the indexes of participants who were in _IA_ or _DQ_.
-In theory this would save space almost every time,
-as the longest message (_MixedSuccess_) may only contain
-1/4 of participants in either of them.
-A less ridiculous ternary encoding would be squeezing 5 trits into 1 byte
-between 0-242, using 8 bytes where binary encoding would use 10.
-These trytes could be further compressed by prefixing them with bytes
-encoding which trytes of the entire array contain any nonzero values,
-saving a small amount of space in most cases.
-In practice there is no way it would be worth it,
-especially given the reputation of ternary in this industry.)
-
-== Dispute resolution
-
-Given that the protocol is performed off-chain,
-participants may submit incorrect results
-in an attempt to gain advantage.
-By relying on the honest majority assumption,
-this can be mitigated by having participants vote on results.
-
-Voting on results means that only votes need to be counted on-chain;
-validating everything else can be offloaded onto the honest majority.
-This has significant cost advantages as _O(n^2^)_ blockchain operations,
-including _O(n)_ transactions and up to _O(n^2^)_ elliptic curve operations,
-can be replaced with simply _O(n)_ transactions of mostly constant size,
-or a single transaction with _O(n)_ elliptic curve operations.
-
-There are two main ways this voting can be performed:
-either by members signing valid results, which are then verified on-chain,
-or by designated members being eligible to submit a result
-which may be challenged by others if they consider it incorrect.
-
-=== Full signing w/ ECDSA (FE)
-
-The _full signing_ technique of voting is simple.
-The designated eligible submitter _P~sub~_ publishes the correct result
-which is then checked by the contract to contain at least _M~max~ + 1_
-valid signatures from unique members of _P_.
-
-This technique requires fewer transactions and is less complex to implement,
-but bears a constant cost as _O(n)_ signatures must be validated on-chain
-upon every group creation.
-Assuming for the sake of example _N = 201_ and _M~max~ = 100_,
-and that `ecrecover = 3000 gas` dominates the transaction fees,
-the cost of full signing would be constant on the order of 325,000 gas.
-
-If every participant in the group signs a result,
-the unnecessary signatures can be pruned to ensure constant
-size and cost of the result submission transaction.
-
-This also sets a hard limit on the group size of _N < gasLimit / 3000_,
-but in practice this would only happen with impractically large groups
-(currently more than 2,000 participants).
-
-It is easy to see why _full signing_ would be correct:
-if _M~max~_ is the largest number of malicious participants,
-requiring _M~max~ + 1_ signatures means that any result accepted by the system
-must have at least one honest participant supporting it.
-
-.costs
-|===
-|Operation |Cost
-
-|`EcrecoverGas`
-|3,000
-
-|Verification with _H = 101_
-|324,000
-
-|Verification with _H = 201_
-|624,000
-
-|Verification with _H = 500_
-|1,021,000
-|===
-
-=== Full signing w/ BLS (FB)
-
-By using a BLS group signature instead of individual ECDSA signatures,
-the on-chain size of the result can be significantly reduced.
-However, pairing checks are extremely expensive,
-even if EIP-1108 gets passed.
-
-Given that the length of the BLS signature would be 256 bits,
-`k = 2` and the gas price of one pairing operation is currently `260,000`;
-with EIP-1108 the price would fall to `91,000`;
-with Vitalik's version `120,000`.
-
-The full cost of validating a BLS group signature
-by at least _H_ members of _P_ is approximately
-_21000 + 2 * (GPAIRINGBASE + 2 * GPAIRINGPERPOINT) + ECADD * (H - 1)_
-from the necessary `Bn256Add` operations.
-Without cost reductions, this is `570,000` for _H = 101_
-
-.costs
-|===
-|Operation |Cost at status quo |Cost with EIP-1108 |Cost with Vitalik's proposal
-
-|`GPAIRINGBASE`
-|100,000
-|80,000
-|40,000
-
-|`GPAIRINGPERPOINT`
-|80,000
-|5,500
-|40,000
-
-|`ECADD`
-|500
-|50
-|500
-
-|Base cost of BLS verification
-
-|520,000
-|182,000
-|240,000
-
-|Verification with _H = 101_
-|591,000
-|208,000
-|311,000
-
-|Verification with _H = 201_
-|641,000
-|303,000
-|361,000
-
-|Verification with _H = 500_
-|790,500
-|452,500
-|510,500
-|===
-
-=== Escalating votes
-
-As an alternative to the above,
-_escalating votes (EV)_ is a protocol where a result is submitted,
-and accepted if it is not challenged within a specified time limit.
-If multiple results are presented,
-the participants will proceed to submit votes on the results
-iff their preferred result is not in the lead,
-or their vote would break a tie.
-After a certain time limit has elapsed since the last vote,
-a confirmation request transaction may be presented by anybody,
-and the result with the highest number of supporting votes is accepted.
-
-The security of this scheme is less obvious,
-but follows from the honest majority assumption:
-since at least _M~max~ + 1_ honest players are online at the voting stage,
-for any amount of adversary votes _0 < v~m~<= M~max~_
-there will be _v~m~ + 1_ honest participants
-who will outvote the malicious players
-(proof by induction).
-
-This scheme is only suitable for situations where _N >= 2 * M~max~ + 1_,
-due to the reliance on the honest majority assumption.
-If the majority of participants is dishonest,
-the plurality result may be incorrect.
-
-In the worst-case scenario escalating votes will cost
-_(M~max~ + 2) * 21000_ gas to the honest participants,
-or around 2.15 million gas.
-However, the practical cost of using escalating votes would be variable
-and would be expected to be significantly lower most of the time.
-
-Given that a rational adversary who cannot break the honest majority assumption
-will expect to inevitably lose the escalating vote,
-and the cost of the voting is symmetrical
-(submitting one vote costs approximately 21,000 gas,
-so the malicious players will pay _v~m~ * 21000_ gas
-while honest players will pay _(v~m~ + 2) * 21000_ gas in total;
-this means the honest players will always pay exactly
-42,000 gas more than the malicious players regardless of the value of _v~m~_),
-one would expect the escalating votes to usually go unchallenged.
-
-In the example scenario, _EV_ is cheaper than _FE_
-if the average number of votes supporting the highest-voted incorrect result
-is less than 13 out of 200 participants,
-or alternatively if the worst-case scenario occurs at most 1/8 the time.
-
-== Incentives
-
-After performing the group creation correctly,
-participants will be members of _G_
-and eligible for rewards from producing signatures for the random beacon.
-
-The protocol requires some parties to publish transactions on-chain.
-Honest parties publishing correct transactions should be compensated for
-the gas required for these transactions.
-
-Malicious parties who violate the protocol should be penalized.
-
-=== Required transactions
-
-Group selection will be performed as part of a previous transaction.
-
-If using _FS_ for voting on results,
-the protocol will require one particularly expensive transaction.
-If _EV_ is used, a larger number of transactions may be required,
-up to a limit of one transaction from each honest participant,
-but each transaction has a lower cost.
-
-
-Types of possible misbehavior in the execution include:
-
-* sending malformed messages
-** malicious only
-* presenting inconsistent shares
-** malicious only
-* voting for incorrect outcome
-** can be done by honest participant
-if the broadcast channel assumption fails
-
-Ways a participant may be inactive during execution:
-
-* inactivity in the beginning
-* inactivity during the execution
-* inactivity at result stage
-** not signing correct result if using FV
-** with EV it gets super complex and don't want to think about it
diff --git a/docs-v1/random-beacon/dkg/terms.adoc b/docs-v1/random-beacon/dkg/terms.adoc
deleted file mode 100644
index 25e6e49b34..0000000000
--- a/docs-v1/random-beacon/dkg/terms.adoc
+++ /dev/null
@@ -1,148 +0,0 @@
-= Terms used in distributed key generation (DKG)
-
-== Time limits
-
-[horizontal]
-T~p~::
-
-Time limit for phase _p_ of the key generation; after _T~p~_ has elapsed every
-non-inactive participant is assumed to have broadcast its own message for phase
-_p_ and received others' messages
-
-T~DKG~::
-
-Time limit for the distributed key generation to finish and _P~1~_ to submit the
-result
-
-T~STEP~::
-
-Time limit after which the next participant in queue becomes eligible to submit
-the result
-
-T~VOTING~::
-
-Time limit after which any disputes over the correct result are assumed to be
-resolved, with the plurality being honest
-
-T~RESPONSE~::
-
-Extension to the time limit after a new vote has been submitted, to ensure
-honest members are able to react to last-minute votes.
-
-== Rewards and punishments
-
-[horizontal]
-R~DKG_SUBMIT~::
-Reward for the member submitting the finally accepted result
-
-D~DKG_MISSED_SUBMISSION~::
-Penalty for all members _P~1~ .. P~i-1~_ who failed to submit the result
-before _P~i~_, if _i > 1_
-
-D~DKG_DQ~::
-Penalty for members on the disqualified list
-
-
-== Values at the time of group creation
-
-[horizontal]
-V~i~::
-**_i_**th output of the random beacon
-
-S::
-The set of all stakers at the time of _V~i~_
-
-P::
-The candidate group of players selected from _S_ with _V~i~_,
-who will try to perform the key generation to create signing group _G_
-
-P~j~::
-__j__-th node in _P_ based on the group candidate selection algorithm
-
-== Values in the DKG protocol
-
-[horizontal]
-IA~p~::
-The set of nodes in _P_ that first failed to broadcast a required message within
-a specified time limit in phase _p_ and were thus added to the set of inactive
-nodes after that phase
-
-IA::
-IA~1~ + IA~2~ + ...
-+
-The set of inactive nodes in _P_ (nodes that failed to broadcast a required
-message within a specified time limit during the DKG)
-
-DQ~p~::
-The set of nodes in _P_ that were disqualified in phase _p_ for provably and
-attributably violating the protocol
-
-DQ::
-DQ~1~ + DQ~2~ + ...
-+
-The set of all disqualified nodes in _P_
-
-G~p~::
-G~p-1~ - IA~p-1~ - DQ~p-1~
-+
-The set of nodes in _P_ that were active and well-behaved at the
-beginning of phase _p_ (_G~1~= P_)
-
-G::
-P - IA - DQ
-+
-The successfully created group after removal of inactive
-and misbehaving nodes
-
-== Keys
-
-[horizontal]
-X~i~::
-Long-term ECDSA private key of _P~i~_
-
-Y~i~::
-Long-term ECDSA public key of _P~i~_
-
-x~ij~::
-Ephemeral ECDH private key of _P~i~_ for the purpose of encrypted communication
-with _P~j~_
-
-y~ij~::
-Ephemeral ECDH public key of _P~i~_ for the purpose of encrypted communication
-with _P~j~_
-
-k~ij~ = k~ji~::
-ECDH(x~ij~, y~ij~)
-+
-Symmetric key generated by _P~i~_ for encrypting and decrypting communications
-with _P~j~_
-
-X::
-X = Σ z~i~
-+
-The (virtual) private key corresponding to the group _G'_
-
-Y::
-Y = X * P1
-+
-The public key corresponding to the group _G'_
-
-z~i~::
-z~i~ = a~i0~
-+
-Piece of the group private key _X_ generated by _P~i~_
-
-y~i~::
-y~i~ = z~i~ * P1 = A~i0~
-+
-Piece of _P~i~_ of the group public key _Y_
-
-x~i~::
-x~i~ = Σ s~ji~
-+
-The individual private key of _P~i~_ corresponding to a share of _X_ at _i_
-
-gx~i~::
-gx~i~ = x~i~ * P1 = Σ (s~ji~ * P1)
-+
-The individual public key of _P~i~_ corresponding to a share of _Y_ at _i_
diff --git a/docs-v1/random-beacon/glossary.adoc b/docs-v1/random-beacon/glossary.adoc
deleted file mode 100644
index 7edec05cc9..0000000000
--- a/docs-v1/random-beacon/glossary.adoc
+++ /dev/null
@@ -1,62 +0,0 @@
-== Glossary
-
-Stake:: An amount of KEEP that is bonded in order to participate in the
- threshold relay and, optionally, the Keep network. Part or all of this can be
- removed from escrow as penalties for misbehavior, while part or all of it can
- be refunded if and when a participant chooses to withdraw in orderly fashion
- from the network and relay.
-
-Staker:: A staking client that has a stake, but may not yet be in a signing
- group.
-
-Minimum Stake Amount:: The minimum stake amount that will make a staking client
- a staker, as required by the staking smart contract.
-
-Stake Amount:: Total KEEP deposited for a single stake.
-
-Signing Member:: One member of one complete signing group in the threshold
- relay.
-
-Signing Group:: One complete signing group in the threshold relay.
-
-Lead Signing Group:: The signing group that will produce the next relay entry
- candidate (due to being the result of $E_i mod N$ with $E_i$ being the
- current entry and $N$ being the number of groups). If this group fails to
- respond to the request in time, the lead responsibility may shift to another
- group.
-
-Relay Entry Candidate:: A random number generated by the threshold relay that
- has not yet been finalized on the blockchain; may be invalid.
-
-Relay Entry:: A relay entry candidate that has been finalized on the blockchain;
- may be invalid.
-
-Keep Client:: The entire application running on a user's system, which contains
- multiple subclients for the various pieces of the Keep system.
-
-Staking Client:: The part of the Keep Client that stakes and participates in the
- threshold relay.
-
-Verifying Client:: Verifies entries on-chain and reports invalid entries.
- Optional, does not require a stake. Reward for identifying an invalid random
- number on the chain.
-
-Provider Client:: The Keep Provider piece of the application, which can in turn
- have workers for various Keep types.
-
-Keep Type:: The functionality that the given Keep relies on for providing
- security. e.g. an SHM (Secure Hardware Module) Keep, SMPC (Secure Multi-Party
- Computation) Keep, Proxy Reencryption Keep, etc.
-
-Provider Worker:: One worker that runs the code to allow a provider client to
- participate in a given Keep Type.
-
-Keep Provider:: One economic entity in the Keep network; has a stake, must
- participate in a signing group as a single member.
-
-Keep:: Up to 1MB of encrypted storage across one or more Keep Providers.
-
-KEEP:: Token used to stake. Can be represented as a K with a vertical bar
- through it.
-
-Keep Owner, Delegate, Requester are described in the whitepaper.
diff --git a/docs-v1/random-beacon/group-expiration/index.adoc b/docs-v1/random-beacon/group-expiration/index.adoc
deleted file mode 100644
index 45d26ae9e4..0000000000
--- a/docs-v1/random-beacon/group-expiration/index.adoc
+++ /dev/null
@@ -1,532 +0,0 @@
-= Group expiration
-
-Desired qualities:
-
-- larger pool of groups when demand is high
-- pool doesn't grow _O(n)_ with output demand
-- stakeless members are minimized
-- the expiry cannot be manipulated
- - any function where stakers can impact which groups expire first is
- vulnerable to manipulation
-- any group expires eventually
-- groups churn reliably and the system doesn't get stuck in a state favoring any
-particular staker(s)
-- number of available groups never hits zero
-
-Thus:
-
-- the number of outputs within a certain time period determines how fast groups
-expire -> to cater for DKG failures, calculate by number of groups instead?
-- small number of outputs -> long expiry
-- large number of outputs -> short expiry
-
-Represent the group expiration function by _Expire(GG, E) -> GG'_ where _GG_ is
-the pool of currently active groups, _E_ is some value representing all other
-inputs to the function, and _GG'_ is the new pool after removing expired groups.
-
-== Expiry manipulation
-
-If the actions of stakers can impact which groups expire first, it enables
-manipulation.
-
-==== Unstake manipulation
-
-Consider a scenario where groups with unstaking members expire faster. Mallory
-blitzpantses their stake _Stake~m~_ to allotments of _Stake~minimum~_ and is
-represented in groups with an average fraction of
-_Rep~m_average~ = Stake~m~ / Stake~total~_.
-
-Then, Mallory proceeds to unstake all of their identities that are only present
-in groups _G~i~_ where _Rep~m_i~ < Rep~m_average~_. Those groups will be removed
-from the group pool faster, and replaced with groups where the expected fraction
-of Mallory's nodes is _Rep~m_average~_.
-
-==== Selection seed manipulation
-
-Consider a scenario where Mallory can influence the value _E_ which determines
-which groups expire with the function _Expire(GG, E)_.
-
-Now Mallory can calculate what values of _E~m~_ within their control would yield
-favorable outputs from _Expire(GG, E~m~)_.
-
-=== Preventing manipulation
-
-To avoid issues of this general nature, _Expire(GG, E)_ should use values of _E_
-that cannot be manipulated. Some suitable values may be:
-
-- The actual outputs of the random beacon (_V~i~_)
-- Current blockheight (_T~j~_) when used in a linear fashion: if _G~i~_ would
-expire with input _T~j~_, it should expire with all inputs _T~j+k~_ where _k > 0_
-- Historical, statistical data about the beacon usage (_BeaconData_) when used to
-eg. tune expiration sensitivity so that more groups remain in the pool if the
-beacon is busy
-- The state of the group pool (_GG_) is also suitable but is already accounted for
-separately
-
-Some values that are definitely unsuitable, unless mixed with good inputs in a
-suitable way:
-
-- Block hashes: miners can influence block hashes to select different groups for
-expiry
-- Details of requests: requesters can influence these inputs
-- The state of the staker pool: stakers, especially blitzpantsing ones, can
-manipulate these values
-- Blockheight as a seed to a pseudorandom function: miner censorship can delay
-processing of transactions to force the use of new seeds that produce a
-different outcome for expiration
-- Seeding a pseudorandom function with statistical data seems risky and is not
-recommended
-
-To summarize:
-
-- Data under adversary control should not be used without effective sanitization
-- Data the adversary can affect in very limited ways is usable as input to
-functions that don't exhibit the avalanche effect
-- Data that is out of anyone's effective control should be safe
-
-==== Rationale
-
-===== Why you shouldn't prf on the blockheight
-
-What happens if we do the unsafe thing and avalanche the blockheight as a seed
-for pseudorandom expiration?
-
-If the size of the group pool is _n~GG~_, the delay window is _T~m~_, and the
-average delay between group expirations is _T~e~_, Mallory has _T~m~_ attempts
-to produce the most favorable/least unfavourable outcome. Since in a stable
-group pool (and one where every DKG succeeds) each group has a _1 / n~GG~_
-chance of expiring, Mallory's favourite group can only expire if all outcomes
-would lead to its expiration, the probability of which is _1 / n~GG~^T~m~^_.
-
-If we assume every expiration trigger event expires exactly one group (for
-simplicity), and Mallory controls _m_ groups, the probability of that expiring
-group being Mallory's is is normally _m / n~GG~_. If Mallory gets _T~m~_
-expiration rerolls, this goes to _m^T~m~^ / n~GG~^T~m~^_. This means that
-Mallory can stabilise a new equilibrium where Mallory's number of controlled
-groups _m'_ is such that
-_m'^T~m~^ / n~GG~^T~m~^ = m / n~GG~_
-
-_m'^T~m~^ / n~GG~^(T~m~ - 1)^ = m_ +
-_m'^T~m~^ = m * n~GG~^(T~m~ - 1)^_
-
-_m' = nthRoot(T~m~, (m * n~GG~^(T~m~ - 1)^))_
-
-or as an example, with _n~GG~ = 300 , T~m~ = 3, n~m~ = 10_, we get:
-
-_m'^3^ = 10 * 300^2^ = 900,000_ +
-_m' = 96.5_
-
-Thus an enemy who normally could only control 3.3% of the groups in network can
-stabilise a 32% control fraction. With _T~m~ = 4_ it goes to 43%, and _T~m~ = 5_
-means 51% control.
-
-===== Can we prf on statistics?
-
-While manipulating blockheight requires only miner censorship, manipulating
-beacon history and statistical data is much more involved and requires
-requesting and paying for new outputs.
-
-Superficially it would appear that the cost of manipulating group expiration in
-such a way would exceed the benefits, but a thorough calculation would need to
-address complex aspects of marginal pricing and external incentives.
-
-There isn't really a good reason to feed statistics as input to pseudorandom
-functions, and thus the effort is better spent elsewhere.
-
-== Possible schemes
-
-Due to the previous, we are left with essentially two classes of expiry
-functions.
-
-=== Limited Lifespan
-
-Timed expiration takes the current blockheight _T~now~_ as input and outputs which
-group(s) should expire.
-
-The groups need to be in an unchanging order. If the groups' expiration order
-can change (eg. by re-shuffling groups whenever a new one is added), it enables
-manipulation by Mallory forcing a re-shuffle just before _G~j~_, where
-_Rep~m_j~> Rep~m_average~_, would expire.
-
-Timed expiration should not exhibit "evaporative cooling" either; a group should
-not get lucky with a seed value that makes it enduringly less likely to expire
-than others.
-
-Because of the above requirements, it seems that expiration with blockheight as
-input is effectively limited to ordering groups by
-_ExpirySeed~j~ = T~j_creation~ + e~j~_
-where _e~j~_ is a non-manipulateable value specific to _G~j~_, and expiring
-groups where
-_T~now~ > ExpirySeed~j~ + c_
-where _c_ is a non-manipulateable value common to all groups.
-
-There seems to be no particular advantage in _e~j~ != 0_ and thus the formula
-can be simplified to
-_T~now~ > T~j_creation~ + c_
-where _c_ acts as the maximum age of a group. Let this form of timed expiration
-be called _limited lifespan_.
-
-==== Limited lifespan manipulation
-
-Timed expiration has a slight manipulation opportunity if a group is on the
-verge of expiry and the transaction that would trigger group expiration can be
-delayed by eg. miner censorship.
-
-This is possible to mitigate by having such a transaction include a reference
-blockheight that must be higher than the blockheight of the previous such
-transaction but the same or lower than the current blockheight when the
-transaction is mined. However, the impact is limited and specific mitigation
-may not be necessary or useful when counterbalanced by the additional complexity
-required.
-
-===== Why it is unavoidable
-
-If the trigger transaction happens at time _T_, group _G~i~_ will not expire. If
-the transaction happens at _T' > T_, group _G~i~_ will expire. Mallory dislikes
-group _G~i~_ and is able to delay the trigger transaction to block _T'_.
-
-If the trigger transaction is a different transaction than the one that selects
-the next signing group for output _V~j~_:
-
-- If the transaction arrives at _T_, group _G~i~_ does not expire, and is
-present in the pool from which the group to output _V~j~_ is selected
-- If the transaction arrives at _T'_, group _G~i~_ expires, and is absent from
-the pool for _V~j~_. Mallory's goal is achieved.
-
-If the trigger transaction is the same one which selects group to produce output
-_V~j~_, we get two different scenarios based on whether expiration is applied
-before selection (so any groups that expire are removed from the pool for
-_V~j~_), or after (so even expiring groups are eligible for _V~j~_ but will be
-removed from the pool for any later outputs).
-
-If expiration is applied before selection:
-
-- At _T_, _G~i~_ doesn't expire, and is thus eligible for _V~j~_
-- At _T'_, _G~i~_ has expired and is not eligible for _V~j~_. Mallory's goal is achived.
-
-If expiration is applied after selection:
-
-- At _T_, _G~i~_ is eligible for _V~j~_, and is also not removed and thus stays in
-the pool for _V~j+1~_ as well
-- At _T'_, _G~i~_ is eligible for _V~j~_ despite being marked for expiration,
-but it will not be in the pool for _V~j+1~_. Mallory's goal is achieved on the
-next output.
-
-===== Is it worth it?
-
-If the size of the group pool is _n~GG~_, the delay window is _T~m~_, and the
-average delay between group expirations is _T~e~_, Mallory has:
-
-- _1 / n~GG~_ chance of denying _G~i~_ the signing position on a successful attack
-- on any given trigger event there is an expected probability of _T~m~ / T~e~_
-of there being a group whose expiry can be manipulated (if Mallory can delay a
-transaction by 3 blocks, and a group expires on every 100th block on average, it
-gives a 3% chance that a group expiration would occur within that window)
-- a _R~m~ - R~i~_ return, where _R~m~_ is the average reward Mallory would get
-if any group except _G~i~_, and _R~i~_ is the reward Mallory would (expect to)
-get if _G~i~_ produces an output
-
-(assuming we only need to consider one group at a time)
-
-for a total return on the attack of _(R~m~ - R~i~) * T~m~ / T~e~ * n~GG~_.
-
-To put some numbers on this, let's assume the active group pool _n~GG~ = 300_,
-_T~m~ = 3, T~e~ = 100_ as above, and Mallory has an average of 5 members in a
-group but only 1 in _G~i~_, we get:
-
-_(5R~signer~ - 1) * 3 / 100 * 300 = 12R~signer~ / 30,000 = 0.0004 * R~signer~_
-of expected value per trigger event of doing this attack, or
-_0.0133 * R~signer~_ value per actual attack with a 0.03 chance of being able to
-attack on any given trigger event.
-
-=== Random Expiration
-
-With random expiration, each group is assigned a pseudorandom expiration seed
-value upon the expiration trigger transaction, and groups whose seed values fall
-below a specific threshold are removed from the pool. Thus each group has an
-equal chance of being removed.
-
-== Expiration thresholds
-
-Both timed and random expiration can be tuned to exhibit desirable
-characteristics. The maximum age and expiration seed value threshold will be
-referred to as simply "expiry threshold".
-
-==== Absolute expiration
-
-At each expiration trigger transaction, calculate the desired number of groups
-_n_. If _|GG| > n_, expire _|GG| - n_ groups by setting the threshold accordingly.
-
-==== Probabilistic expiration
-
-Choose parameters for the functions that calculate the expiry threshold so that
-the expected value of _|GG'|_ is _n_.
-
-=== Group churn
-
-It is desirable to have adequate turnover in beacon signing groups. Because a
-group selection is triggered by every beacon output, new groups will be reliably
-added to the pool if the DKG finishes most of the time. Assuming a group pool of
-constant size and a DKG that never fails, each group would produce one output
-before expiring, on average. If the DKG has a failure rate of _f_, a group would
-be expected to sign _1 / (1 - f)_ outputs.
-
-It seems desirable to decouple group expiration from DKG success to reduce the
-effectiveness of manipulating the group pool by deliberately inducing DKG
-failure. This has two implications:
-
-1. DKG success should not be the group expiration trigger
-2. The group expiration should be probabilistic, not absolute
-
-=== Group pool size
-
-TODO: check the math, does pool bias compound the variability in staker profits?
-Taking a small sample of (small sample of large pool) vs. small sample of (large
-sample of large pool); reconcile w/ churn and individual staker's perspective.
-
-When the group pool is small, group lifespan is relatively short and the
-probability of an active group being selected for any given output is relatively
-high. Smaller pools are less representative of the pool of stakers, and may be
-more susceptible to pool composition manipulation.
-
-With a large pool, each group's (expected) lifespan is relatively long, while
-each group's chance of being selected for any specific output is low. A large
-pool is more representative of the stakers, but also more expensive to operate
-due to on-chain processing costs.
-
-=== Stakeless members
-
-To unstake, a staker needs to wait _T~unstake~_ before the tokens are freed. An
-unstaking holder will not be selected for new groups, but they will not be
-removed from groups created earlier. Thus _G~i~_ is guaranteed not to have
-members who have finished unstaking if _T~now~< T~i_creation~ + T~unstake~_.
-
-With older groups there is a possibility that some members may have nothing at
-stake and thus cannot be penalized for misbehavior. This can be prevented by
-either extending the unstaking waiting period until the staker is no longer
-a member of any active group, or by removing those members from the group and
-possibly expiring the group if the number of remaining members falls below
-_N - M~nofail~_.
-
-With limited lifespan, these issues can be prevented entirely by setting a cap
-on the maximum lifespan at _T~unstake~_ as long as at least 1 DKG can be relied
-on to finish successfully within any period of _T~unstake~_.
-
-==== Extended unstaking delay
-
-===== Under random expiration
-
-With random expiration, the probability of a group expiring within the unstaking
-period _P~expire~(T~unstake~)_ determines the likelihood of this becoming a
-severe issue. Call the probability that a group is still active when a member
-finishes unstaking
-_P~leftover~ = 1 - P~expire~(T~unstake~)_.
-
-Because the age of a group doesn't impact the expiry probability under random
-expiration, each unstake event has a _P~leftover~_ chance of leaving the member
-in the group. After _2T~unstake~_ the probability is _P~leftover~^2^_, and so
-on for
-_1 - P~expire~(x * T~unstake~) = P~leftover~^x^_.
-If _P~leftover~_ is low enough, for example _0.001_, this should be reasonably
-uncommon. However, the non-deterministic unstaking period creates a severe tail
-risk for stakers, which may have a larger-than-expected impact on the value of
-the token.
-
-===== Under limited lifespan
-
-If group lifespans have a systemwide hard cap at _T~maxlife~_, blocking
-unstaking until a staker's groups have expired means that the real unstaking
-period _T'~unstake~_ is
-_T~unstake~ <= T'~unstake~<= T~maxlife~_.
-
-The actual value of _T'~unstake~_ for _S~i~_ can be estimated in advance with
-some accuracy, using knowledge of the ages of the groups _S~i~_ is represented
-in, and the formula for calculating group lifespans:
-_c = F~maxlife~(GG, BeaconData)_.
-This works even if no systemwide constants are used, although varying beacon
-conditions will create some unpredictability.
-
-==== Removing stakeless members
-
-If _S~i~_ is represented as _P~i~_ in _G~j~_, but finishes unstaking while
-_G~j~_ is still active, _P~i~_ could be removed from _G~j~_ so they will not be
-able to collect rewards for contributing to future outputs. The probability of
-this occurring for any given unstaking under random expiration is _P~leftover~_.
-
-If _n_, the number of members remaining in _G~j~_ after DKG is closer to _N_
-than _N - M~nofail~_, single members unstaking should not pose a significant
-problem.
-
-If a large number of members unstake, _n~remaining~ = n - n~unstaked~_ may fall
-below _N - M~nofail~_ and residual security may be compromised. It may be
-desirable to terminate a group if
-_n~unstaked~ + n~dkg_inactive~ + n~dkg_disqualified~ > M~nofail~_.
-
-If groups terminate when too many members unstake, it opens up a group pool
-manipulation attack where _S~m~_ blitzpantses and then unstakes groups where
-they control
-_m >= M~nofail~ - (n~dkg_inactive~ + n~dkg_disqualified~)_
-members.
-
-This ties down _m * Stake~min~_ KEEP for _T~unstake~_ and has _P~leftover~_
-probability of success. Assuming the blitzpantsing divides _S~m~_'s tokens in
-such a way that any blitzpantsed staker identity is represented in at most one
-group in _GG_ (expected number of representations per an identity with
-_Stake~min~_ being
-_Stake~min~ * N * |GG| / Stake~total~_),
-the opportunity cost is as follows:
-
-TODO: actually calculate this
-
-== Terminating groups
-
-In some situations a group may need to be terminated before it would expire
-normally.
-
-=== Member attrition
-
-If enough members are removed from the group so that _n~remaining~ < H_,
-termination is the only option to preserve beacon reliability.
-
-Termination may be desirable if the group loses enough members to push it below
-the threshold of _n~remaining~ < N - M~nofail~_, to preserve residual security.
-
-===== Technical requirements
-
-As qualified members of each group are tracked, no additional capabilities are
-required to be able to terminate groups incapable of reaching quorum.
-
-===== Punishment
-
-In the case of termination due to member attrition, the remaining participants
-should not be penalized, especially if member attrition below _N - M~nofail~_ is
-used as the termination threshold.
-
-If the punishment for each remaining member is _D~terminate_attrition~_ and the
-lowest punishment for misbehavior that leads to _P~m~_ being removed from the
-group is _D~dropout~_, punishing remaining members enables control bootstrapping
-attacks if
-_D~terminate_attrition~ * (N - M~terminate~) > D~dropout~ * (M~terminate~ - n~dkg_removed~)_ +
-_= D~terminate_attrition~ > D~dropout~ * (M~terminate~ - n~dkg_removed~) / (N - M~terminate~)_ +
-_= D~terminate_attrition~ / D~dropout~ > (M~terminate~ - n~dkg_removed~) / (N - M~terminate~)_ +
-where +
-_n~dkg_removed~ = n~dkg_inactive~ + n~dkg_disqualified~_ +
-and _M~terminate~_ is the threshold at which number of removed members the group
-is terminated, with probability equal to the adversary controlling
-_M~terminate~ - n~dkg_removed~_
-members in the group.
-
-If punishing the subquorum group is desired, it will be safe if:
-
-----
-D_ta / D_d < (M_t - n_dr) / (N - M_t)
-D_d / D_ta > (N - M_t) / (M_t - n_dr)
-----
-
-at _n~dkg_removed~ = M~nofail~_: +
-_D~dropout~ / D~terminate_attrition~ > (N - M~terminate~) / (M~terminate~ - M~nofail~)_
-
-
-
-If _M~terminate~ = M~nofail~ + 1 = (N - 1) / 4 + 1_, +
-the above becomes +
-*_D~dropout~ / D~terminate_attrition~ > (3N - 3) / 4_*
-
-----
-D_d / D_ta > (N - M_nf - 1) / (M_nf + 1 - M_nf)
-D_d / D_ta > N - M_nf - 1
-D_d / D_ta > N - (N - 1) / 4 - 1
-D_d / D_ta > (4N - N + 1) / 4 - 4/4
-D_d / D_ta > (3N - 3) / 4
-----
-
-Thus a safe punishment for a group falling under quorum would need to be
-extremely small.
-
-If _M~terminate~ = M + 1 = (N - 1) / 2 + 1_, +
-we get the requirement +
-*_D~dropout~ / D~terminate_attrition~ > 2 - 8 / (N + 3)_*
-
-----
-D_d / D_ta > (N - M - 1) / (M + 1 - M_nf)
-D_d / D_ta > (N - (N - 1) / 2 - 1) / ((N - 1) / 2 - (N - 1) / 4 + 1)
-D_d / D_ta > ((2N - N + 1) / 2 - 1) / ((N - 1) / 4 + 1)
-D_d / D_ta > ((N + 1) / 2 - 1) / ((N - 1) / 4 + 1)
-D_d / D_ta > (N/2 - 1/2) / (N/4 + 3/4)
-D_d / D_ta > (2N - 2) / (N + 3)
-D_d / D_ta > (2N + 6 - 8) / (N + 3)
-D_d / D_ta > (2(N + 3) - 8) / (N + 3)
-D_d / D_ta > 2 - 8 / (N + 3)
-----
-
-In this case, as long as the punishment for each remaining group member is less
-than half of the smallest dropout punishment, the punishments can be given
-without enabling arbitrary power bootstrapping attacks. Nonetheless, punishing a
-disproportionately honest group of stakers for something caused by the actions
-of the other members is not recommended.
-
-Punishing the removed members in the case of failure to stay in quorum is
-possible if removed members are flagged as disqualified for rewards while
-remaining on the list of the original group members.
-
-=== Compromised private key
-
-If the group private key has been exposed or the group is proven to collude in
-signing invalid values, the group should be terminated to preserve beacon
-security.
-
-===== Technical requirements
-
-This can be achieved by tracking the values _Input~i~_ signed by the group to
-generate outputs _V~i~_. Because each group signs on average
-_1 + Prob~dkg_failure~ / Prob~dkg_success~_ inputs before expiring, this would
-not lead to excessively expensive record-keeping.
-
-If a valid signature on value _Input~m~_ is made using the public key of _G~j~_,
-and _Input~m~_ is not present in the list of values _G~j~_ has signed in the
-beacon operation, _G~j~_ should be terminated.
-
-===== Punishment
-
-Because signing such an invalid value requires at least _H_ members to misbehave
-or have their individual private keys compromised, punishing the entire group
-may seem safe and appropriate even if the specific guilty parties cannot be
-identified.
-
-However, control bootstrapping attacks are possible if +
-_D~terminate_compromise~ * M > D~min_compromise~ * (H - n~dkg_dq_late~ - 1) + D~terminate_compromise~ - R~tattletale_compromise~_ +
-where +
-_D~min_compromise~= min(D~terminate_compromise~, D~dropout~)_, +
-_n~dkg_dq_late~_ members are disqualified in phase 9 of the DKG, and +
-_R~tattletale_compromise~_ is the reward for the actor presenting proof of the
-violation.
-
-Thus no amount of punishment is entirely safe if _n~dkg_dq_late~ > 1_.
-
-The probability of success equals the probability of the adversary controlling
-_m = H - n~dkg_dq_late~_ members in the group, with the minimum being
-_m = M~nofail~ + 1_ with _n~dkg_dq_late~ = M~nofail~_.
-
-The control bootstrap multiplier for this attack in the most favorable case is:
-_(D~tc~ * M) / (D~mc~ * M~nf~ + D~tc~ - R~tc~)_.
-Defining _R~tc~ = a * D~tc~_ where _a < m~mc~_ gets:
-_(D~tc~ * M) / (D~mc~ * M~nf~ - (a - 1) * D~tc~)_
-Define _r = D~tc~ / D~mc~_:
-
-----
-_(r * M) / (M~nf~ - (a - 1) * r)_
-_(r * M) / (M/2 - (a - 1) * r)_
-_2(r * M) / (M - (2a - 2) * r)_
-_2r * M / (M - 2ar + 2r)_
-----
-
-simplifying to:
-
-_2r + 4r^2^ * (a - 1) / (M - 2ar + 2r)_
-
-Because _a_ should be larger than 1 to incentivize burning a compromised group
-even if you have a node in it, and lower than _M/2_ to disincentivize actively
-seeking to collude and loot other stakers, the _2r_ factor is the most relevant.
-Consequently the required economic power for this attack is roughly
-_50% * min(1, D~dropout~ / D~terminate_compromise~)_ of the honest participants'
-power.
diff --git a/docs-v1/random-beacon/group-expiration/terms.adoc b/docs-v1/random-beacon/group-expiration/terms.adoc
deleted file mode 100644
index 4374262749..0000000000
--- a/docs-v1/random-beacon/group-expiration/terms.adoc
+++ /dev/null
@@ -1 +0,0 @@
-= Terms used in group expiration
diff --git a/docs-v1/random-beacon/group-selection/general.adoc b/docs-v1/random-beacon/group-selection/general.adoc
deleted file mode 100644
index fa04b78273..0000000000
--- a/docs-v1/random-beacon/group-selection/general.adoc
+++ /dev/null
@@ -1,207 +0,0 @@
-= General group selection
-
-Functionality contracts in the Keep network require groups of stakers
-to perform operations.
-
-== Basic description
-
-The _group selection contract_ provides a mechanism
-for selecting a group of stakers in a representative way.
-Each staker has a chance of being selected
-that is proportional to their _staker weight_.
-
-When a _functionality contract_ needs a new group,
-it calls the `initiateGroupSelection` method on the _group selection contract_.
-The _functionality contract_ is required to provide
-a _selection seed_, and the _group size_ of the desired group (_n_).
-
-When the `initiateGroupSelection` method is called,
-_stakers_ may begin submitting _tickets_
-to show their eligibility for the new group.
-
-Each ticket contains the _staker ID_ of its _creator_,
-the _selection seed_ of the group it is for,
-and a _ticket index_ used to distinguish the _creator's_ different tickets.
-With these, a pseudorandom _ticket value_
-and a unique _ticket identifier_ can be calculated.
-
-Tickets with the lowest _ticket values_ are the most favorable.
-Each staker can create a number of tickets equal to its _staker weight_.
-Stakers with promising tickets of a low _ticket value_
-can submit them on-chain until _ticket submission timeout_ is reached.
-
-Once _ticket submission timeout_ is reached,
-the new group can be created by calling `finishGroupSelection`
-which returns the best _n_ tickets.
-
-In the future, alternative group selection contracts can be created
-to provide different features,
-such as staker indistinguishability.
-
-== Details
-
-=== Tickets
-
-A ticket consists of the triplet `(selection_seed, staker_ID, ticket_index)`.
-
-Ticket values are calculated as
-`sha3(selection_seed, staker_ID, ticket_index)`.
-The _ticket index_ is a value between 1
-and the _staker weight_ of the ticket's creator, inclusive.
-Each staker can submit a number of tickets equal to their staker weight.
-
-Because `sha3` is pseudorandom,
-each ticket has an independent chance of being in the _n_ best tickets.
-This means a given staker may be included multiple times in the same group.
-This independence of tickets is considered desirable
-to simplify the group selection protocol
-while also ensuring that it cannot be manipulated
-by distributing stakes in any particular way.
-The _staker weight_ of staker _Alice_
-is equal to the number of separate stakers Alice could form with their stake.
-Thus Alice cannot gain more tickets by distributing their stake
-over more than one staker identity.
-
-=== Threshold
-
-The _threshold_ is the value of the _n_-th best ticket;
-after the _ticket submission deadline_,
-there are _n_ tickets with values at or below the _threshold_.
-
-=== Ticket submission
-
-The contract is agnostic to how tickets are submitted
-as long as the transactions are processed before the ticket submission deadline.
-To avoid unnecessary transactions,
-it is recommended that clients submit their best tickets first as follows:
-
-When instructed to submit more than one ticket at once
-the staker should submit the most favorable one,
-wait a block, submit the next most favorable one,
-and so on.
-
-Calculate the values of each ticket the staker is eligible to submit.
-Order the tickets by favorability;
-with tickets of the lowest value first.
-
-==== Natural threshold and initial submission
-
-Calculate the _natural threshold_.
-The _natural threshold_ is the value the _threshold_ would take
-if all tokens in existence were staked with maximum efficiency
-and the ticket values were evenly distributed in the domain of `sha3`.
-----
-max_stakers = token_supply / minimum_stake
-natural_threshold = (group_size / max_stakers) * (2^256 - 1)
-----
-
-If the staker has any tickets below the _natural threshold_,
-those tickets should be submitted immediately.
-
-Most of the time there are less than _n_ tickets below the natural threshold,
-because the tokens are not staked in the most efficient possible way
-and some stakers may be inactive or unable to submit their tickets.
-
-==== Continued submission
-
-If less than _n_ tickets are submitted immediately,
-the remaining tickets should be scheduled:
-
-For each ticket, calculate the scheduled submission delay
-by calculating how many multiples of the natural threshold the ticket value is,
-and multiplying the _submission delay increment_ by that number.
-----
-submission_delay(t) = ((t.value / natural_threshold) - 1) * delay_increment
-----
-Add the submission delays to the _group selection initiation time_
-to get the time each ticket is scheduled to be submitted.
-----
-submission_time(t) = initiation_time + submission_delay(t)
-----
-
-Submit each remaining ticket at the indicated time,
-until at least _n_ tickets with lower values than the next ticket
-have been submitted.
-
-[NOTE]
-.Submission delay
-====
-The protocol isn't particularly sensitive
-to the exact value of the _submission delay increment_.
-If the increment is too small,
-it may lead to the premature submission of ultimately ineligible tickets.
-If the increment is too large,
-it may lead to others submitting ultimately ineligible tickets.
-
-Major problems would occur only where the submission delay increment
-is set to such a high value that an ultimately eligible ticket
-fails to get processed before the deadline.
-This can be avoided by calculating and using
-a worst-case delay increment:
-----
-natural_threshold_fraction = group_size / max_stakers
-delay_increment_count = (1 / natural_threshold_fraction) - 1
-delay_increment = submission_period / delay_increment_count
-----
-
-With the worst-case delay increment
-every possible ticket value gets scheduled within the submission window.
-
-To illustrate:
-----
-group_size = 50
-max_stakers = 10,000
-natural_threshold = 0.005 * (2^256 - 1)
-
-natural_threshold_fraction = 1/200
-delay_increment_count = 199
-delay_increment = submission_period / 199
-----
-Because the natural threshold is 1/200-th of the domain,
-on average 1 in 200 tickets would fall below it.
-The remaining 199 out of 200 tickets are scheduled
-so that the worst possible ticket `2^256 - 1`
-would get submitted just at the end of the submission window.
-
-For practical applications,
-this worst-case delay increment is extremely pessimistic
-and would cause unnecessary transaction fees to its user.
-====
-
-=== Processing tickets
-
-Tickets are submitted by calling the method
-`submitTicket(selection_seed, staker_ID, ticket_index)`.
-
-The _selection seed_ is used
-to identify which group selection each ticket belongs to,
-as there may be multiple group selections running in parallel.
-Submitting a ticket whose selection seed is invalid,
-or where the corresponding group selection not accepting new tickets,
-should lead to the ticket being *discarded*.
-
-The _staker ID_ is used to identify the staker that created the ticket.
-The staker must exist,
-its status must be _Active_ (it may not be in the process of unstaking),
-and it must have _authorized_ the contract corresponding to the selection seed.
-Tickets failing these criteria should be *discarded*.
-
-The _ticket index_ is used to distinguish different tickets
-when a staker whose weight is more than 1
-is eligible to submit multiple tickets,
-and to act as a nonce for the pseudorandom function
-to ensure different tickets get independent values.
-The ticket index should be between 1 and the _staker weight_
-of the staker corresponding to the _staker ID_, inclusive.
-Tickets with a ticket index outside these bounds should be *discarded*.
-
-Ticket values of valid tickets are calculated as
-`sha3(selection_seed, staker_ID, ticket_index)`.
-
-=== Finishing
-
-Once the _ticket submission deadline_ has been reached,
-the method `finishGroupSelection(selection_seed)` can be called.
-It returns the best _n_ tickets in ascending order of ticket value.
-These tickets are assigned the numbers from _1_ to _n_ inclusive,
-and these numbers are used as _member indices_ for the resulting group.
diff --git a/docs-v1/random-beacon/group-selection/index.adoc b/docs-v1/random-beacon/group-selection/index.adoc
deleted file mode 100644
index 7455314ba6..0000000000
--- a/docs-v1/random-beacon/group-selection/index.adoc
+++ /dev/null
@@ -1,311 +0,0 @@
-:toc: macro
-
-= Random Beacon Group Selection
-
-ifndef::yellowpaper[toc::[]]
-
-The group selection protocol is intended to be
-an interactive method of selecting candidate group _P_
-from the set of all stakers _S_
-given a pseudorandom seed value _V~i~_.
-
-Functional interface:
-
-inputs: _S, V~i~_
-
-output: _P_
-
-The protocol should:
-
-. [[req-1]]produce a representative result,
-where each staker's profit is proportional
-to the number of tokens they have staked
-. [[req-2]]produce a group _P_ of constant size _N_
-. [[req-3]]not require an excessive amount of on-chain operations to perform
-. [[req-4]]not be feasible for an adversary to manipulate
-
-.Some terms
-|===
-|Term |Meaning
-
-|Trenchcoating
-|Several actors pooling up their stakes under one staker identity
-to take advantage of rich-get-richer effects.
-Thus what seems to be a large staker is actually
-"a hundred small stakers in a trenchcoat".
-
-|Blitzpantsing
-|The inverse of trenchcoating; a single token holder dividing their stake
-under multiple identities to avoid rich-get-poorer effects or to increase their
-representation in groups.
-This can increase profits above what is designed, or make certain attacks easier
-to perform by making one actor more likely to control a group.
-Thus what seems to be a large number of small stakers is actually a single
-whale in an "inverse trenchcoat", or "blitzpants".
-
-|Non-interactive
-|A protocol is non-interactive if it can be performed without stakers
-providing additional information.
-Specifically, _S~i~_ can determine whether they are in _P_
-without input from other stakers in _S_.
-
-|Interactive
-|An interactive protocol requires stakers to provide additional information
-over what is available on-chain,
-and then performs a deterministic algorithm to select a group
-based on the information provided by the stakers.
-In an interactive protocol _S~i~_ cannot know for sure
-whether they are in _P_ before they receive the other stakers' input.
-
-|Actual staker
-|An actor holding and staking at least _MINIMUM_STAKE_ tokens,
-represented as _S~i~_.
-Each actual staker corresponds to one or more virtual stakers.
-An actual staker can be represented multiple times in a candidate group,
-through multiple virtual stakers.
-The surplus tokens above _n * MINIMUM_STAKE_ (for an integer _n_)
-do not impact the actual staker's ability to create virtual stakers.
-
-|Virtual staker
-|A construct used to simplify
-the mathematical requirements of the group selection protocol
-and ensure blitzpantsing provides no advantage.
-
-Each virtual staker represents exactly _MINIMUM_STAKE_ tokens
-staked by some actual staker who may or may not be anonymous.
-A virtual staker may only ever be included once in a candidate group,
-and _N_ properly denotes the number of virtual stakers in _P_.
-
-|Ticket
-|A message containing a pseudorandomly generated value _W~k~_ which is used to
- determine whether a given _virtual staker_ is eligible for the group _P_ (the
- lowest _N_ tickets will be chosen) and a proof of the validity of the value
-
-|Threshold
-|The value of the highest-valued ticket in _P_
-
-|_Space~tickets~_
-|Is a space consisting of all possible tickets. It is strongly related
-with a pseudorandom function that is used for ticket generation.
-Currently the _Space~tickets~_ is equal to _2^64^- 1_, which is due
-to selection of the first 8 bytes of keccak256
-as our pseudorandom function.
-
-|_Supply~tokens~_
-|Is the total number of tokens which are going to be supplied during the project
-lifetime and is set to 10^9.
-
-|Natural threshold
-|_Threshold~nat~ = floor(N * Space~tickets~ / (Supply~tokens~ / MINIMUM_STAKE))_
-
-In other words, the natural threshold is the value _N_ virtual stakers' tickets
-would be expected to fall below if the tokens were optimally staked, and the
-tickets' values were evenly distributed in the domain of the pseudorandom
-function.
-
-Usually _Threshold~P~ > Threshold~nat~_ as not all tokens will be staked and the
-distribution of stakes will not be optimal.
-|===
-
-== Setup
-
-When a staker _S~j~_ is created, the following values are determined:
-
-- _Stake~j~_: the amount of tokens staked by _S~j~_ and thus locked up until the
- staker is destroyed
-- _Weight~j~= floor(Stake~j~ / MINIMUM_STAKE)_: the staking weight of _S~j~_;
- how many virtual stakers can represent _S~j~_
-- _Address~j~_: the operator address of _S~j~_
-
-== Protocol
-
-A new output _V~i~_ is generated by the random beacon. This triggers the
-selection of a new candidate group.
-
-=== Phase 1: ticket calculation
-
-_S~j~_ calculates _Ticket~k~ = (value~k~, vs, Address~j~)_ where:
-
-- the ticket value is calculated as _value~k~ = prf(V~i~, Address~j~, vs)_
-- the virtual staker number _vs_ is within the range _1 <= vs <= Weight~j~_
-- the staker weight _Weight~j~_ is correct for the operator address _Address~j~_
-
-=== Phase 2: ticket submission
-
-==== Phase 2a: initial ticket submission
-
-Each staker whose _value~k~ < Threshold~nat~_ on one or more _Ticket~k~_ publishes
-the ticket/s.
-
-The operator contract checks the validity of each submitted ticket
-by querying the staking contract
-for the stake available to the operator in the ticket,
-calculating the corresponding staker weight,
-checking that the virtual staker index _vs_ is within the allowed bounds,
-and verifying that _value~k~_ is correct.
-Invalid tickets are rejected.
-
-Phase 2a ends when _TICKET_INITIAL_TIMEOUT_ is reached.
-
-==== Phase 2b: reactive ticket submission
-
-If the number of tickets received in phase 2a is less than _N_, the stakers
-whose tickets did not fall below the natural threshold will publish theirs.
-
-Tickets should ideally be published in order, to reduce the costs of ticket
-submission on the stakers. For this, it is recommended that tickets where
-_W~k~ = x * Threshold~nat~_ be submitted at time _x * TICKET_INITIAL_TIMEOUT_,
-IFF the number of tickets below _W~k~_ is less than _N_.
-
-When tickets are published in order, the number of unnecessary transactions can
-be minimized, which benefits the stakers. Thus it would be in each staker's
-interests to follow the regular order. This, however, is only a recommendation
-and tickets submitted at different times should not be rejected.
-
-Phase 2b ends when _TICKET_SUBMISSION_TIMEOUT_ is reached.
-
-=== Phase 3: threshold determination
-
-After all potentially eligible tickets have been submitted,
-the _N_ tickets with the lowest values for _value~k~_
-will be selected into the group _P_.
-The corresponding virtual stakers
-will be automatically assigned to form the group
-and no further interaction is necessary.
-DKG will be performed.
-
-== Notes and rationale:
-
-=== Virtual stakers
-
-Due to the use of virtual stakers, the stakers will be expected to be
-represented in _P_ with a probability proportional to their _Weight~j~_; a
-staker staking at least _2 * MINIMUM_STAKE_ may also be selected multiple times
-for the same group.
-
-This makes the result representative and ensures that neither blitzpantsing nor
-trenchcoating will provide the staker greater profits than they could acquire
-otherwise (<>), with the exception that pooling token
-amounts below _MINIMUM_STAKE_ and sharing the risk and profits would enable the
-utilization of smaller holders' tokens or surplus tokens from regular stakers.
-This form of trenchcoating is arguably either neutral or beneficial, and in any
-case it does not violate proportionality of rewards.
-
-=== Interactive protocol
-
-There would be two simple non-interactive options but neither is able to
-satisfy all of the requirements:
-
-1. One method would be to have each _S~j~_ calculate a pseudorandom value
-_Seed~j~_, and then everybody whose _Seed~j~ < Threshold~i~_ is in _P_.
-_Threshold~i~_ would be calculated using public information,
-eg. by _Threshold~i~ = floor(N * Space~tickets~ / |S|)_ for a 256-bit _Seed~j~_.
-However, this means that due to random chance, most of the time _|P| != N_.
-This violates <>.
-2. Alternatively each staker could present some kind of a hashed value
-_Hash~j~_ so that whether _S~j~_ is in _P_ can be determined publicly
-by _f(V~i~, Hash~j~, S, N) -> Bool_.
-This cannot work, because then anybody could
-calculate _f(V~m~, Hash~j~, S, N)_ for a large number of different values _V~m~_
-and see how often _S~j~_ ends up eligible for the candidate group.
-Due to <> this necessarily reveals how much _S~j~_ has staked
-to an arbitrary degree of precision, violating <>.
-
-These constraints seem inherent in the problem, and thus an interactive protocol
-appears necessary. The aforementioned issues can be avoided by having _S~j~_
-calculate a value _W~j~_, so that _S~j~_ will be in _P_ if _Threshold~P~ > W~j~_.
-
-[source, python]
-----
-all_tickets = []
-for S_j in S:
- for vs in [1..Weight_j]:
- W_k = prf(V_i, Q_j, vs)
- all_tickets.append(Ticket(W_k, proof(W_k))
-
-Threshold_P = max(all_tickets.map(fn(t): t.W_k).sort().take(N)
-----
-
-Assuming once again 256-bit values for _W~k~_ and _Threshold~P~_,
-_S~j~_ can predict their expected probability of being in _P_
-by calculating how likely it would be that _Threshold~P~ > W~k~_.
-Then _S~j~_ can broadcast their input only if there seems to be
-a realistic chance that they could be selected.
-If it seems likely that _Threshold~P~ < W~k~_,
-_S~j~_ can refrain from broadcasting _W~k~_ and only monitor the situation,
-reacting if it seems that few stakers' ticket values are falling under
-the estimated threshold.
-
-== Alternative off-chain protocol
-
-This protocol was not chosen but is included in the yellowpaper to illustrate
-reasoning and what alternatives were considered
-
-=== Protocol
-
-Each staker calculates their tickets
-
-Each staker who has one or more ticket/s that may be eligible for the group
-broadcasts the ticket, including proof of its validity
-
-Other stakers check broadcasted tickets for validity; if an invalid ticket is
-broadcast, the ticket is rejected
-
-After _T~selection~_ has elapsed, stakers following the broadcast channel
-select _N_ tickets with the lowest value to form the candidate group
-
-Each member of the candidate group BLS-signs a message
-containing all the tickets of the group and the threshold
-
-This is the _Group Formation Message_, signed by _[P~1~..P~N~]_ to ensure the
-integrity of the group selection process. Because all participants are required
-to sign the _Group Formation Message_, the group composition cannot be
-manipulated later.
-
-The members of _P_ perform DKG; at the end of DKG the final message contains:
-
-- DKG output, similarly BLS signed
-- group formation message
-- aggregate BLS signature of the above
-
-On-chain receives DKG conclusion message, and:
-
-- checks that all stakers in the group formation message are valid
-- checks the proofs supplied in the tickets
-- checks that all tickets are below the threshold
-- checks that the group formation message is signed by everyone in _P_
-and that the DKG output is signed by at least _H_ members of _P_
-
-If two or more valid group formations are presented,
-the one with the lowest threshold wins
-
-Any virtual staker is only permitted to sign a group formation message for one
-group (any given ticket may only be used for one group); if a ticket is used for
-two or more different groups, the staker should be penalized
-
-Submitting only a group formation message without DKG conclusion is also valid
-and signifies that the group was formed, but DKG did not reach quorum (_H_
-participants would not agree on any given result)
-
-However, if a group formation message is published it may be superseded by a
-valid DKG conclusion message for the same group
-
-If a member of group _P_ with _Threshold~P~_ publishes a valid group formation
-message, and a member of group _P'_ with _Threshold~P'~_ publishes a valid group
-formation and DKG conclusion message:
-
-- if _P ∩ P' != {}_, the stakers who signed both group formation messages should
- be penalized, but the groups _P_ and _P'_ may still be valid (this is to
- prevent an attack where one member of an unfavorable group prevents the group
- creation by signing and publishing a different, unrelated group creation message)
-- if _Threshold~P~ > Threshold~P'~_, group _P'_ is to be considered the correct
- group and the group selection is to be deemed a success.
-- if _Threshold~P~ < Threshold~P'~_, group _P_ is to be considered the correct
- group and the group selection is to be deemed a failure.
-- if _Threshold~P~ = Threshold~P'~_, group _P'_ is to be considered the correct group
-
-
-=== Notes
-
-The off-chain protocol is much more complex to secure effectively, and a variety
-of attacks on the group composition need to be addressed.
diff --git a/docs-v1/random-beacon/group-selection/terms.adoc b/docs-v1/random-beacon/group-selection/terms.adoc
deleted file mode 100644
index 50bccecdd9..0000000000
--- a/docs-v1/random-beacon/group-selection/terms.adoc
+++ /dev/null
@@ -1 +0,0 @@
-= Terms used in group selection
diff --git a/docs-v1/random-beacon/group_selection.py b/docs-v1/random-beacon/group_selection.py
deleted file mode 100644
index c770a789f7..0000000000
--- a/docs-v1/random-beacon/group_selection.py
+++ /dev/null
@@ -1,242 +0,0 @@
-class GroupSelectionContext:
- stakers: Map[StakerID, Staker]
- tickets: TicketDataStructure
- V_i: BlsSignature
- T_init: BlockHeight
-
-
- def T_elapsed(T_amount: BlockHeight) -> bool:
- """
- Determine if a given amount of time has elapsed (in blocks)
- """
- T_now = getCurrentBlockHeight()
- return T_now - T_init >= T_amount
-
-
- def receiveTicket(t: Ticket):
- if t in tickets:
- ignore(t)
- elif cheapCheck(t):
- tickets.add(t)
- else:
- punish(t.sender, INVALID_TICKET_PENALTY)
-
-
- def cheapCheck(t: Ticket) -> bool:
- """
- Cheap check to perform on-chain on every ticket reception
- """
- t_staker = stakers[t.sender]
-
- valid_Q_j = t.proof.Q_j == t_staker.address
- valid_vs = t_staker.weight() > t.proof.vs >= 1
-
- return valid_Q_j && valid_vs
-
-
- def receiveChallenge(challenge: Challenge):
- if not challenge.ticket in tickets:
- # Challenged ticket not found
- # eg. it has already been successfully challenged and removed
- ignore(challenge)
-
- elif costlyCheck(challenge):
- punish(challenge.sender, INVALID_CHALLENGE_PENALTY)
-
- else:
- tickets.remove(challenge.ticket)
-
- punish(challenge.ticket.sender, INVALID_TICKET_PENALTY)
-
- reward(challenge.sender, TICKET_TATTLETALE_REWARD)
-
-
- def costlyCheck(challenge: Challenge) -> bool:
- """
- Costly check to perform on-chain when a ticket is challenged;
- assumes the ticket passes cheapCheck()
-
- Not very costly in current version (only sha3) but enables forward
- compatibility with future ZKP implementations
- """
- t = challenge.ticket
- p = t.proof
-
- ticket_valid = getTicketValue(V_i, p.Q_j, p.vs) == t.value
- return ticket_valid
-
-
- def runGroupSelection() -> List[StakerID]:
- """
- Run the entire group selection protocol:
-
- Start by receiving tickets or challenges,
- perform a cheapCheck on each received ticket
-
- After timeout for tickets is over, wait a bit for challenges
-
- For each received challenge, perform costlyCheck
- and punish the misbehaving party
- """
- T_init = getCurrentBlockHeight()
-
- while not T_elapsed(TICKET_SUBMISSION_TIMEOUT):
- t = receive()
-
- if isTicket(t):
- receiveTicket(t)
- elif isChallenge(t):
- receiveChallenge(t)
- else:
- ignore(t)
-
- while not T_elapsed(TICKET_CHALLENGE_TIMEOUT):
- c = receive()
-
- if isChallenge(c):
- receiveChallenge(c)
- else:
- ignore(c)
-
- # Now we have received the tickets and challenges
- # Time to select the group candidate
-
- # Get the N tickets with the lowest values
- bestTickets = tickets.query(N)
- # P is the virtual stakers corresponding to those tickets
- P = bestTickets.map(sender)
-
- # Staker S_i may be represented multiple times in P if they have many
- # tokens and get lucky. In this case we simply proceed normally, with
- # multiple participants P_j, P_k etc. corresponding to the same actual
- # staker S_i.
- return P
-
-
-class TicketDataStructure:
- """
- TicketDataStructure is an abstraction which takes in tickets
- and keeps them sorted in order: lowest ticket value first
- """
- def add(t: Ticket):
- def remove(t: Ticket):
- def query(n: int) -> List[Ticket]:
-
-
-class Ticket:
- """
- A Ticket contains a pseudorandom value which is used to determine whether
- a given virtual staker is in the candidate group P
- """
- value: Sha3Digest # corresponds to W_k
- proof: TicketProof
- sender: StakerID
-
-
-class TicketProof:
- """
- A TicketProof is an abstraction for the information necessary to determine
- whether a ticket is valid
- """
- vs: int
- Q_j: Address
-
-
-class Challenge:
- """
- A Challenge is a signed claim that a given ticket is invalid
- """
- ticket: Ticket
- sender: StakerID
-
-
-def getTicketValue(
- V_i: BlsSignature,
- Q_j: Address,
- vs: int
-) -> Sha3Digest:
- """
- Utility function to clarify how ticket values are determined with sha3
- """
- return sha3(asBytes(V_i) ++ asBytes(Q_j) ++ asBytes(vs))
-
-
-class Staker:
- address: Address
- ecdsaPubkey: EcdsaPubkey
- blsPubkey: BlsPubkey
- stakedTokens: TokenAmount
-
-
- def weight() -> int:
- """
- A staker's weight is how many minimum-stake stakers a given actual staker
- could form if they were to blitzpants their stake
-
- By creating a number of virtual stakers corresponding to the weight of each
- actual staker, we remove the incentive to blitzpants
- """
- return floor(stakedTokens / MINIMUM_STAKE)
-
-
- def tickets(V_i: BlsSignature) -> List[Ticket]:
- """
- Generate all the tickets of a given staker, in sorted order
-
- The leading tickets in the resulting list can be queried for promising ones
- """
- virtualStakers = range(1, weight())
- Q_j = s.address
-
- createdTickets = []
- for vs in virtualStakers:
- W_k = getTicketValue(V_i, Q_j, vs)
- newTicket = Ticket(W_k, TicketProof(vs, Q_j))
- createdTickets.append(newTicket)
-
- return createdTickets.sort_ascending(value)
-
-
- def runGroupSelection():
- unpublished = tickets()
- tNat = naturalThreshold()
-
- # Publish all tickets that fall under the natural threshold
- while unpublished.first().value < tNat:
- promisingTicket = unpublished.pop()
- publish(promisingTicket)
-
- while not T_elapsed(TICKET_INITIAL_TIMEOUT):
- wait()
-
- while not T_elapsed(TICKET_SUBMISSION_TIMEOUT):
- t = getLatestSubmission()
-
- if isTicket(t) and not isValid(t):
- c = Challenge(t, self)
- publish(c)
-
- # If it seems like we would have another ticket eligible for P,
- # publish the most promising ones. This prevents dumping all tickets
- # at once before others have had time to publish theirs, but should
- # be decently responsive anyway.
- currentBestTickets = getContract().tickets.query(N)
- currentBestThreshold = max(currentBestTickets.map(value))
-
- bestTicket = unpublished.first()
- bestTicketEligible = bestTicket.value < currentBestThreshold
- timeToPublish = bestTicket.value * TICKET_INITIAL_TIMEOUT / tNat
-
- if bestTicketEligible and T_elapsed(timeToPublish):
- unpublished.pop()
- publish(bestTicket)
-
- # Group selection done, see if we are in P
- P = getContract().tickets.query(N).map(sender)
-
- if P.contains(self):
- runDKG()
- else:
- obvserveDKG()
-
-
diff --git a/docs-v1/random-beacon/incentives.adoc b/docs-v1/random-beacon/incentives.adoc
deleted file mode 100644
index e1547a91bb..0000000000
--- a/docs-v1/random-beacon/incentives.adoc
+++ /dev/null
@@ -1,394 +0,0 @@
-= Incentives
-
-When an operator misbehaves attributably, the corresponding stake should be
-slashed. Punishments should be appropriate for the severity of the misbehavior
-and its impact on the network, and can be between _0_ and _Stake~MIN~_.
-
-== Rewards and punishments
-
-All rewards and punishments are incurred by a specific virtual staker.
-
-STATUS: proposal
-
-Currency and token rewards are paid to the beneficiary address specified in the stake
-delegation transaction.
-
-Punishments are performed by removing the designated amount of tokens from the
-stakes of the _owner_.
-
-If the operator has enough free stake to cover a minor penalty, the virtual
-staker may continue performing operations and the penalty is subtracted from the
-free stake, possibly impacting the operator's eligibility for subsequent group
-selections.
-
-If the operator cannot pay a minor penalty from free stake, the virtual staker
-is terminated to avoid a stake deficit. When a virtual staker is terminated it
-is removed from any groups it is in, rendering it ineligible for further rewards
-from participating in those groups, and locking the remaining stake
-_Stake~remaining~ = Stake~MIN~ - D_ for _T~UNSTAKE~_, after which
-_Stake~remaining~_ is added to the operator's free stake.
-
-TODO: do we want to lock the stake like this if terminated?
-
-Major penalties always include termination of the virtual staker, regardless of
-the free stake available. A major penalty may be smaller in absolute amount than
-a minor penalty (but probably not); the distinction reflects the nature of the
-misbehavior.
-
-=== Group selection
-
-==== Rewards
-
-Group selection has no intrinsic rewards. However, presenting a valid challenge
-to an invalid ticket should be amply rewarded to preserve the integrity of the
-interactive protocol.
-
-R~TICKET_TATTLETALE~::
-
-Token reward for operator that presents a valid challenge to an invalid ticket.
-+
-_R~TICKET_TATTLETALE~ < D~INVALID_TICKET~_
-+
-It may be desirable for _R~TICKET_TATTLETALE~_ to include both tokens and
-currency. `CostlyCheck` is expected to be expensive to perform in the future,
-and submitting a valid ticket challenge should always be profitable. If the
-ticket tattletale reward consists of both tokens and currency:
-+
-_R~TICKET_TATTLETALE~ = R~TICKET_TATTLETALE_TOKENS~ + R~TICKET_TATTLETALE_CURRENCY~_ +
-_R~TICKET_TATTLETALE_TOKENS~ < D~INVALID_TICKET~_ +
-_R~TICKET_TATTLETALE_CURRENCY~ >= GasEstimate(CostlyCheck)_
-+
-However, group selection provides no source of such currency, and thus it would
-need to be taken from a general pool. It may be prohibitively difficult to
-protect such a pool from getting emptied by attackers.
-+
-If the tattletale reward consists of only tokens, it would be profitable if
-_R~TICKET_TATTLETALE~ * TokenPrice > GasEstimate(CostlyCheck)_.
-
-==== Punishments
-
-D~INVALID_TICKET~::
-
-Major
-+
-Penalty for any operator that presents an invalid ticket. The invalid ticket may
-fail either `CheapCheck`, or `CostlyCheck` after being challenged.
-+
-The requirements on _R~TICKET_TATTLETALE~_ constrain the value of
-_D~INVALID_TICKET~_:
-+
-_D~INVALID_TICKET~ > GasEstimate(CostlyCheck) / TokenPrice_
-+
-This is necessary to ensure that the incentives of challenging invalid tickets
-are in place.
-
-D~INVALID_CHALLENGE~::
-
-Major
-+
-Penalty for operator that presents an invalid challenge, and the accused ticket
-passes `CostlyCheck`. Because the gas costs of `CostlyCheck` are incurred by the
-accuser, _D~INVALID_CHALLENGE~_ can be set relatively freely without significant
-impact on the incentives of the group selection protocol.
-
-=== DKG
-
-==== Rewards
-
-R~DKG_SUBMITTER~::
-
-The member submitting the finally accepted result is paid a submission reward.
-The distributed key generation has no rewards for non-submitting members. The
-prospect of future rewards from signing beacon outputs provides the incentive to
-participate in the DKG.
-
-==== Punishments
-
-D~DKG_MISSED_SUBMISSION~::
-
-Minor
-+
-The DKG expects the first member _P~1~_ of the candidate group _P_ to submit
-the result. If the finally accepted result is submitted by _P~i~, i > 1_, each
-_P~1~ .. P~i-1~_ are penalized by D~DKG_MISSED_SUBMISSION~.
-
-D~DKG_DQ~::
-
-Minor
-+
-As the DKG is performed off-chain, only a list of disqualified participants is
-produced. Thus all actual misbehavior necessarily has the same penalty. A member
-on the list of disqualified members will be penalized by D~DKG_DQ~.
-+
-*TODO: minor penalty?*
-+
-The penalty is minor despite reflecting potentially severe protocol violations
-because the misbehavior was not proven on-chain. A colluding cartel that
-controls the created group can forcibly disqualify even well-behaved members.
-
-=== Signing
-
-When publishing beacon outputs on-chain, there are two possible outcomes for an
-output:
-
-- if the output fails the BLS signature check, punish the submitter
-- if the output passes the check, reward submitter and other members
-
-==== Variable stakes and rewards
-
-To incentivize paying more for the beacon outputs, siging rewards and penalties
-are adjusted by _RequestMultiplier~i~_ whose value depends on how much has been
-paid for _V~i~_.
-
-_RequestMultiplier~MAX~_ is the highest value _RequestMultiplier_ can take.
-
-Penalties are limited by the value +
-_Stake~REQUEST_BASE~ = Stake~MIN~ / RequestMultiplier~MAX~_ +
-so that the highest penalty at the highest request value multiplier is equal to
-the maximum penalty of _Stake~MIN~_.
-
-==== Rewards
-
-R~submitter~(T), R~group~(T)::
-
-The submitter and group reward will vary over time, where _T_ is the time it
-takes to publish the valid output on-chain (_T' > T_):
-+
-_R~submitter~(T) > R~group~(T)_
-+
-The submitter is always rewarded more than the other members. This is partially
-to cover the gas fees of submitting the beacon output (expensive BLS
-verification), and partially to incentivize submissions.
-+
-_R~submitter~(T) <= R~submitter~(T')_ +
-_R~group~(T) >= R~group~(T')_
-+
-Over time, the submitter reward grows while the group reward declines. If the
-group takes long enough to submit the output, the group reward can go negative.
-+
-_R~total~(T) = R~submitter~(T) + (N - 1) * R~group~(T)_ +
-_R~total~(T) >= R~total~(T')_
-+
-The total reward for the entire group (submitter + other members) declines over
-time.
-+
-When _T <= T' <= T~output_expected~_: +
-_R~submitter~(T) = R~submitter~(T')_ +
-_R~group~(T) = R~group~(T')_ +
-_R~total~(T) = R~total~(T')_
-+
-The maximum possible reward is given out when the output is submitted within
-_1 <= T <= T~output_expected~_ from the reveal of the value to be signed. Within
-this window there is no difference in rewards between different submission
-times.
-+
-When _T' > T > T~output_expected~_: +
-_R~submitter~(T) < R~submitter~(T')_ +
-_R~group~(T) > R~group~(T')_ +
-_R~total~(T) > R~total~(T')_
-+
-If _T > T~output_expected~_, the total reward is lower, the submitter reward
-grows every block, and the group reward declines every block.
-+
-The value of _T~output_expected~_ may be set by the output request, or it may be
-a global constant. If _T~output_expected~ = 1_ there is no constant-reward
-window.
-+
-_R~selfish~(T, m) = R~submitter~(T) + (m - 1) * R~group~(T)_ +
-_R~selfish~(T, M~nofail~) > R~selfish~(T', M~nofail~)_
-+
-Because of the selfish signing attack, the submitter reward should not grow
-faster than a moderate multiple of the group reward declines, to avoid creating
-an incentive to delay output publication.
-+
-A hard limit for this is when _m = M~nofail~_. This is because it takes _H_
-honest participants to produce an output, and the minimum number of active
-participants in a group is _H + M~nofail~_ if _M~nofail~_ members have been lost
-in DKG. If an actor controls less than _M~nofail~_ members in a group, there
-should be enough other members that the output can be completed without the
-adversary's input. This cannot be guaranteed when _m > M~nofail~_, and thus
-selfish signing should always be unprofitable in such a case.
-+
-_R~group~(T~late~) = D~late_output~(T~late~)_ when _T~late~ > T~MAX_OUTPUT_DELAY~_
-+
-If the group takes particularly long to submit the output, the group reward can
-go negative. In this case instead of rewarding the group members in _$CURRENCY_,
-their stakes are slashed.
-
-==== Punishments
-
-D~INVALID_SIGNATURE~::
-
-Major
-+
-If an invalid signature is submitted, its submitter is to be penalized by
-_D~INVALID_SIGNATURE~ * RequestMultiplier_.
-+
-_D~INVALID_SIGNATURE~ <= Stake~REQUEST_BASE~_
-+
-The invalid signature penalty is limited by the base stake.
-
-D~late_output~(T)::
-
-Minor
-+
-_R~group~(T~late~) = D~late_output~(T~late~)_ when _T~late~ > T~MAX_OUTPUT_DELAY~_
-+
-If the group takes particularly long to submit the output, the group reward can
-go negative. In this case instead of rewarding the group members in _$CURRENCY_,
-their stakes are slashed. Additionally, the unreliable group is terminated.
-+
-_D~late_output~(T) < D~late_output~(T')_
-+
-To ensure an incentive to submit a late output remains, the penalty should grow
-over time.
-+
-_D~late_output~(T~OUTPUT_FAILURE~) = Stake~REQUEST_BASE~_
-+
-If the output is not submitted within _T~OUTPUT_FAILURE~_, every member in the
-group is penalized by _Stake~REQUEST_BASE~ * RequestMultiplier_.
-
-==== Anchored rewards
-
-It may be desirable to let members prove that a late submission is not their
-fault. A member wishing to anchor their reward would publish the beacon input
-signed by their individual private key, which can be verified by providing the
-corresponding individual public key and the merkle path to the merkle root of
-all individual public keys.
-
-If the signature share submitted at _T_ is valid, the member _P~j~_ would be
-rewarded _R~group~(T) * RequestMultiplier_. _P~j~_ would effectively pay the
-price of the BLS verification to gain immunity from late submission penalties.
-
-If the signature share is invalid, _P~j~_ would be penalized
-_D~INVALID_SIGNATURE~ * RequestMultiplier_.
-
-If a reward has been anchored at _T_ and the full output is submitted at _T'_,
-the submitter reward should be adjusted by the anchoring:
-
-_R~submitter~(T') = (R~submitter~(T) * (1 / N)) + (R~submitter~(T') * (N - 1) / N)_
-
-If multiple rewards have been anchored at _T~1~, T~2~..._ the submitter reward
-should be correspondingly:
-
-_R~submitter~(T') = (R~submitter~(T~1~) / N) + (R~submitter~(T~2~) / N) + (R~submitter~(T') * (N - 2) / N)_
-
-If the submitter reward is not adjusted, it would be possible to extract more
-than the amount available for the rewards.
-
-Anchoring rewards requires publishing and storing the merkle root of individual
-public keys from DKG.
-
-==== Leftover rewards
-
-Because the beacon operation rewards decline over time, the maximum total reward
-may not be paid out. In this case there will be leftovers.
-
-_R~max~ = R~total~(T~output_expected~)_ +
-_R~leftover~(T) = R~max~ - R~total~(T)_
-
-If _R~leftover~(T) > 0_, the surplus needs to be allocated somehow.
-
-Leftover pool::
-
-One possibility is to establish a _leftover pool_ and use the pool to subsidize
-later outputs by an amount determined by the currency balance in the pool:
-
-_Bid'~i~ = Bid~i~ + R~leftover_subsidy~(PoolBalance~i~, Bid~i~)_ +
-_PoolBalance~i+1~ = PoolBalance~i~ - R~leftover_subsidy~(PoolBalance~i~, Bid~i~)_
-
-Leftover refund::
-
-Another possibility is to refund the leftovers to the requester. This could be
-desirable as compensation for slowness of output, but if a large number of
-customers contributed to the request payment it may be inconvenient to refund
-them all proportionally.
-
-=== General
-
-Some rewards and punishments don't fit into a specific category.
-
-==== Individual private key compromise
-
-If a private key is exposed or used inappropriately, the consequences to the
-network could be serious. If the owner of a compromised key is punished for the
-failure to secure it adequately, it can improve the incentives and weed out
-insecure participants.
-
-D~KEY_COMPROMISED~::
-
-Major punishment
-+
-If the individual private key of _P~i~_ is compromised or used to sign an
-inappropriate value _v_, _P~i~_ should be given the major punishment of
-_D~KEY_COMPROMISED~_.
-+
-Compromise of an individual private key can be proven by submitting a message
-signed with the key, along with the corresponding public key and its merkle path
-to the root of the individual public key merkle tree, published in DKG result.
-
-R~KEY_COMPROMISE_TATTLETALE~::
-
-Reward
-+
-An operator who submits proof of an individual private key compromise should be
-rewarded by _R~KEY_COMPROMISE_TATTLETALE~_ tokens.
-+
-_R~KEY_COMPROMISE_TATTLETALE~ < D~KEY_COMPROMISED~_
-
-==== Group private key compromise
-
-If the private group key of any group is compromised, beacon security can be
-violated for outputs assigned to that group. Detection and termination of such
-groups should be incentivized.
-
-D~GROUP_KEY_COMPROMISED~::
-
-Minor punishment
-+
-If the group private key of _G~i~_ is used to sign an inappropriate value _v_,
-every member in _G~i~_ can be punished by _D~GROUP_KEY_COMPROMISED~_. A group
-whose key has been compromised must be terminated.
-+
-Because signing an invalid value requires contribution from at least _H_
-members, the existence of such a signature proves that the honest majority
-assumption has not held. However, because participants disqualified in DKG
-phase 9 have their secret information exposed, it is possible for an adversary
-controlling _M~nofail~ + 1_ members in the group to create such a signature if
-_M~nofail~_ members were disqualified in phase 9. This should be a rare
-occurrence but provides a slight control bootstrapping attack for a sufficiently
-powerful adversary.
-
-R~GROUP_KEY_COMPROMISE_TATTLETALE~::
-
-Reward
-+
-An operator who submits proof of an individual private key compromise should be
-rewarded by _R~GROUP_KEY_COMPROMISE_TATTLETALE~_ tokens.
-+
-_R~GROUP_KEY_COMPROMISE_TATTLETALE~ << M~nofail~ * D~GROUP_KEY_COMPROMISED~_
-+
-The magnitude of the group key compromise tattletale reward has a significant
-impact on the viability of the control bootstrapping attack for deliberately
-compromising the group key.
-
-== Extra notes
-
-=== Tattletale ratio
-
-The operator can still transfer tokens by abusing the tattletale mechanisms.
-However, the efficiency of this is limited by the
-`tattletale_fraction = tattletale_reward / misbehavior_penalty`
-ratio of the best available exploit.
-
-This seems impossible to mitigate because if the operator is paid
-`operator_reward = operator_fraction * expected_value_multiplier * total_stake`
-and thus the opportunity cost of stealing
-`tattletale_fraction * total_stake`
-is negative only when
-`operator_fraction * expected_value_multiplier > tattletale_fraction`.
-However, in this case it becomes profitable to bribe a potential tattletale
-simply with the earnings one will get in the future from the tokens that would
-be slashed if the tattletale would do their job, and only the presence of a
-sufficient number of non-coordinating potential tattletales keeps this from
-being an easy way out.
diff --git a/docs-v1/random-beacon/index.adoc b/docs-v1/random-beacon/index.adoc
deleted file mode 100644
index 9b4bf736ca..0000000000
--- a/docs-v1/random-beacon/index.adoc
+++ /dev/null
@@ -1,172 +0,0 @@
-:toc: macro
-:toclevels: 4
-:yellowpaper:
-
-= The Keep Random Beacon: An Implementation of a Threshold Relay
-
-toc::[]
-
-[abstract]
-.Abstract
---
-The Keep Network requires a trusted source of randomness for the process of
-trustless group election. While the network requires that randomness to function
-correctly, the source of randomness is itself broadly applicable. This trusted
-source of randomness takes the form of a BLS Threshold Relay. We discuss
-implementation of this random beacon, including assumptions and mitigations for
-bad actors and poor network connectivity.
---
-
-== Overview
-
-The threshold relay described herein is a way of generating verifiable
-randomness that is resistant to bad actors both in the relay network and on the
-anchoring blockchain, assumed here to be Ethereum. The basic functioning of the
-relay (further details are in the section on <>) is:
-
-* Some number of groups exist in the relay.
-* An arbitrary seed value _v~s~_ counts as the first entry in the relay.footnote:[The
- importance, from a security perspective, of the seed value goes away almost
- immediately in a functioning network.]
-* A request _r~i~_ is dispatched to the chain for a new entry.
-* The previous entry _v~s~_ is used
-to choose a group to produce the response to the request.
-* _v~s~_ is signed by at least a subset of the chosen group members, and the
- resulting signature is the entry generated in response to the request. It is
- published to the anchoring blockchain as the entry _v~i~_.
-* The new entry _v~i~_ may trigger the formation of a new group from the set of
- all members in the relay.
-* A group expires after a certain amount of time.
-
-The following sections will detail how this basic function is implemented in
-practice, including notes on <> that motivated this design,
-the <> used to economically incentivize good behavior by
-network participants, <> used in the network, and finally the
-<> that outline the implementation itself. <>
-is also discussed.
-
-== Prior Work
-
-Dfinity has described their implementation of a random beacon backed by a
-threshold relay in their consensus whitepaper
-footnote:[https://dfinity.org/pdf-viewer/library/dfinity-consensus.pdf]. The
-relay described in this paper is heavily based on the one devised by the Dfinity
-team, with certain adjustments for implementation on an existing blockchain. The
-key distinction between the Dfinity implementation and the Keep implementation
-is that Keep has to contend with blockchains that do not implement the same
-primitives as the in-house Dfinity chain targeted in their paper. Concerns such
-as transaction costs and payment for beacon entries are therefore a core part of
-the incentive system built around the Keep random beacon.
-
-As described in the above paper, at the heart of the relay beacon is the
-signature scheme described by Dan Boneh, Ben Lynn, and Hovav Shacham in
-footnote:[D. Boneh, B. Lynn and H. Shacham, “Short signatures from the Weil
-pairing”, Advances in Cryptology – ASIACRYPT 2001, Lecture Notes in Computer
-Science, 2248 (2001), 514–532. Full version: Journal of Cryptology, 17 (2004),
-297–319.], termed BLS. Three properties of the scheme are of particular use in
-this case: BLS signatures can be used in _threshold_ mode, where _k_ of _n_
-participants are sufficient to produce a combined signature; BLS threshold
-signatures produce the same final signature irrespective of the participants;
-and BLS signatures are typically shorter than those of many other threshold
-signature schemes.
-
-Finally, underpinning the process of generating new groups for BLS threshold
-signatures in the system is a distributed key generation algorithm based on work
-by Gennaro, Jarecki, Krawczyk, and Rabin footnote:[R. Gennaro, S. Jarecki, H.
-Krawczyk, and T. Rabin. Advances in Cryptology — EUROCRYPT ’99: International
-Conference on the Theory and Application of Cryptographic Techniques Prague,
-Czech Republic, May 2–6, 1999 Proceedings, chapter Secure Distributed Key
-Generation for Discrete-Log Based Cryptosystems, pages 295–310. Springer Berlin
-Heidelberg, Berlin, Heidelberg, 1999 ;
-http://groups.csail.mit.edu/cis/pubs/stasio/vss.ps.gz], as also described in the
-Dfinity paper above. The Keep Random Beacon publishes group public keys to the
-anchoring blockchain and does member selection on-chain, but key generation
-occurs between nodes with only the final result vote occurring on-chain.
-
-== Incentive Structure
-
-The system generates verifiable random numbers using threshold signatures.
-BLS threshold signatures are deterministic,
-so a given signing group can only produce one valid signature
-for any given input.
-A party that knows the private key of a signing group
-can calculate signatures in advance,
-and generated entries can be influenced
-by preventing the selected group from producing a signature
-and thus forcing the beacon to select a different group.
-
-To incentivize participants,
-every member of a group that produces a valid entry is rewarded.
-Participants that perform costly but necessary actions
-are reimbursed for the costs and further rewarded.
-
-Each participant is required to _stake_ a number of tokens
-that are held as collateral against misbehavior.
-Participants staking a greater number of tokens
-have a correspondingly greater opportunity to earn rewards.
-In the event that a group fails to produce a signature when requested
-or its private key is provably abused,
-each member of the group is punished by _slashing_ their stake;
-taking away some or all of their staked tokens.
-
-In some cases,
-misbehavior is proven with the help of a third party _"tattletale"_
-who notifies the beacon of the misbehavior,
-and if necessary, provides the required proof.
-If the misbehavior occurred as claimed,
-the tattletale is rewarded with a fraction of the slashed tokens.
-
-== System Details
-
-The system has two high-level modes of operation, discussed in detail in their
-individual sections:
-
-* Group formation, consisting of group member selection and distributed key
- generation.
-* Threshold signing, triggered by a beacon request and producing a new entry in
- the relay (which in turn also triggers the formation of a new group). signing
- also involves selecting the appropriate price for a new relay entry.
-
-Additionally, the beacon makes money by charging for _beacon requests_. An early
-draft of the pricing mechanism is described in its own section.
-
-=== Group formation
-
-include::group-selection/index.adoc[leveloffset=+3]
-
-include::dkg/index.adoc[leveloffset=+3]
-
-include::signing/index.adoc[leveloffset=+2]
-
-include::pricing.adoc[leveloffset=+2]
-
-include::staking/index.adoc[leveloffset=+2]
-
-include::slashing.adoc[leveloffset=+2]
-
-== Upgrade management
-
-The system has been designed to facilitate upgrades
-without exposing stakers to vulnerabilities
-commonly found in upgradeable smart contracts.
-For this purpose,
-smart contracts in the system are divided into different categories
-based on their purpose and functionality,
-and strict security boundaries are maintained in the design.
-
-Furthermore, the authority to take various actions in the system
-has been divided into a number of roles
-where each role has a specific purpose and domain.
-The roles and their authorizations are designed
-to limit the impact of single key compromise.
-Severely harmful actions such as stealing participants' stakes
-should require the compromise of multiple independent actors
-wherever feasible.
-
-include::contract-structure.adoc[leveloffset=+2]
-
-include::authorizations.adoc[leveloffset=+2]
-
-include::upgrades.adoc[leveloffset=+2]
-
-include::glossary.adoc[]
diff --git a/docs-v1/random-beacon/misbehavior.adoc b/docs-v1/random-beacon/misbehavior.adoc
deleted file mode 100644
index c3f08a8406..0000000000
--- a/docs-v1/random-beacon/misbehavior.adoc
+++ /dev/null
@@ -1,332 +0,0 @@
-= Attacks and misbehavior
-
-== Types of participants
-
-=== Honest
-
-A honest actor will always follow the protocol.
-
-If the return for participating honestly _R~h~_ is below the required rate of
-return (eg. cost of capital, operating expenses), a honest participant will
-abstain from participating, even if a misbehaving course of action is available
-that would yield greater returns.
-
-The protocol should avoid relying on any participants being honest.
-
-=== Greedy
-
-A greedy actor will want to maximize its return.
-
-A greedy actor is willing to violate protocol and misbehave in arbitrary ways if
-doing so has a positive expected value, but will not take action which reduces
-their returns. A greedy actor does not care about the impact on other
-participants unless they have entered a binding contract to share the profits.
-
-A greedy participant will misbehave if and only if the return from doing so
-_R~m~_ is equal or greater than the return from honest participation _R~h~_.
-
-The protocol should be designed to be viable if most participants are greedy. It
-is also to be expected that some greedy participants will have external
-incentives; for example, manipulating a lottery to greatly increase the chance
-of winning may be worth taking a punishment for.
-
-=== Malicious
-
-A malicious actor will seek to subvert or inflict damage on the network.
-
-A malicious actor is willing to misbehave even at an immediate cost to itself,
-at the pursuit of some ulterior motive in opposition to the intended functioning
-of the network.
-
-==== Adversary power
-
-The main constraint on the malicious actor is the amount of resources it has
-available _res~m~_, especially in relation to the resources of the well-behaved
-participants _res~h~_. The ratio _power~m~ = res~m~ / res~h~_ determines the
-_adversary power_ of the malicious actor. Because money can be used to buy
-various forms of influence, it does not seem sensible to assume a malicious
-actor would be limited to any particular type of influence (a fraction of
-stakers only, with no miners, or a fraction of miners but no stakers). Instead,
-a safer assumption is that the adversary can control a fraction of each specific
-type of participant, determined by _power~m~ / (1 + power~m~)_. For example,
-with _power~m~ = 0.5_ the adversary can control 33% of all miners, stakers, etc.
-
-The protocol should be resistant to malicious participants, especially those of
-low adversary power. Any protocol relying on a honest majority is vulnerable to
-adversaries of _power~m~ >= 1_ (a 51% attack).
-
-==== Control bootstrapping
-
-_Control bootstrapping_ is the class of attacks a malicious actor can use to
-increase its share of control over the network, and thus one of the most
-significant. Preventing and limiting control bootstrapping attacks is extremely
-important for protecting against malicious participants.
-
-If an adversary with _power~m~_ power can cause _D~h~_ damage to the
-well-behaved participants at a cost of _D~m~_ to itself, so that
-_D~m~ / D~h~ < power~m~_, the attack would increase the attacker's adversary
-power relative to the well-behaved participants:
-_power'~m~ = (res~m~ - D~m~) / (res~h~ - D~h~) > power~m~_.
-The effectiveness of attack _A_ can be expressed as its _damage multiplier_:
-_mult~A~ = D~h~ / D~m~_. Attack _A_ is useful to adversary _m_ if
-_mult~A~ * power~m~ > 1_.
-
-Such attacks can be used to "smoke out" honest and greedy participants by
-rendering staking unprofitable without the external budget provided by the
-malicious actor's ulterior motives. If an attack can be iterated enough times,
-the well-behaved participants would run out of resources before the adversary.
-Thus over time the adversary would be able to bootstrap a smaller degree of
-control over the network into a larger one.
-
-== Participant status
-
-=== Well-behaved
-
-A well-behaved participant is correctly following the protocol and sending the
-expected messages at expected times.
-
-=== Inactive
-
-An inactive participant is one that has stopped sending the messages expected by
-the protocol, but is otherwise well-behaved. An inactive participant does not
-send invalid messages or otherwise actively undermine the protocol execution.
-
-A participant can be rendered inactive due to internal, such as node
-misconfiguration or downtime, or external factors, such as network problems or
-DoS attacks.
-
-Transient inactivity is expected to be the most common form of protocol
-violation. Care should be taken not to punish such cases excessively harshly,
-especially because, unlike other forms of misbehavior, an attacker can force
-a participant to be inactive.
-
-=== Misbehaving
-
-A misbehaving participant has engaged in active protocol violations by sending
-messages (broadcasting to other nodes, or publishing transactions on-chain) that
-are invalid in either format or content.
-
-Wherever feasible, misbehavior should be attributable and punishable. A third
-party cannot force a non-compromised participant to misbehave attributably, and
-thus any such misbehavior can be blamed on the participant who signed the bad
-message.
-
-==== Compromised participants
-
-An otherwise well-behaved participant whose private key has leaked to a third
-party can be made to misbehave by using the compromised key. This is impossible
-to distinguish from straightforward misbehavior, as an attacker could just as
-well set up a scheme that makes them appear legitimately compromised, but such
-distinction is neither necessary nor desirable. Penalizing the stakers whose
-operators have been compromised acts as an incentive to protect against such
-compromise, and helps remove vulnerable operators from the network.
-
-== Types of misbehavior
-
-=== Incorrect signature share
-
-Instead of broadcasting _Sig~m~_, _P~m~_ broadcasts a different, incorrect
-value _Sig'~m~_ to other members of the signing group.
-
-==== Attributability
-
-*Full*
-
-==== Viability
-
-*Low*
-
-Signature shares can be validated against the individual public key known from
-DKG, and invalid shares ignored.
-
-==== Mitigation
-
-*None* (initially) to *full* (potentially)
-
-Relies on DKG individual public key attributability
-
-Relies on tracking beacon outputs signed by each group
-
-Signing an incorrect value can be proven with the signature that doesn't
-correspond to any previous beacon input, the member's public key, and its merkle
-path to the DKG merkle root.
-
-
-=== Selfish signing - greedy
-
-Instead of revealing their signature share the operator waits to receive shares
-from others, trying to delay others' signature reconstruction and to gain
-the submitter reward.
-
-==== Attributability
-
-*Low*
-
-A signature submission by a node that hasn't broadcast its own signature share
-is evidence of selfish signing, but this can be circumvented by having the
-submitter node broadcast its share normally while the adversary's other nodes
-withhold theirs.
-
-As the signature is reconstructed from shares it is not possible to tell which
-nodes provided the shares for a given submission, and if the adversary
-participates normally on one node its other nodes are indistinguishable from
-offline nodes.
-
-==== Viability
-
-*Moderate* to *high*
-
-The relationship of the derivative of the submitter's reward (grows over time)
-vs the group rewards (declines over time) influences the viability of this
-attack.
-
-If the attack is successful at _T~submit~_, the adversary benefits by
-_R~submitter~(T~submit~) - R~group~(T~submit~)_.
-Because selfish signing results in the signature being submitted later than
-it otherwise would at _T'~submit~_, the full viability of the greedy variant for
-an adversary with _m_ nodes is governed by
-__R~submitter~(T~submit~) + (m - 1) * R~group~(T~submit~) - m * R~group~(T'~submit~)_.
-
-If _R~submitter~(T) > R~group~(T')_ for all _T, T'_, successful selfish signing
-is always profitable when _m = 1_ and will remain profitable for larger _m_ if
-_T_ and _T'_ are close enough.
-
-If the selfish signing is unsuccessful, the operator will lose out on
-_m * (R~group~(T'~submit~) - R~group~(T~submit~))_
-which is small if _T_ is close to _T'_.
-
-Additionally, delaying the submission deliberately can be profitable when
-_dR~submitter~ / dT + (m - 1) * dR~group~ / dT > 0_ (always for _m = 1_).
-
-If the system is modeled as a theoretical broadcast channel and the adversary
-as rushing, the attack will always succeed. In a real system the probability of
-success increases with _m_; a true linchpin adversary with
-_m + n~inactive~ + n~disqualified~ > M_
-will always succeed at selfish signing. Variability in message transmission
-time reduces success chances as a different member may have their signature
-reconstructed by the time _P~m~_ has received _H - m_ shares. Miner censorship
-and DoS attacks on the other participants can improve chances of success.
-
-==== Mitigation
-
-*None* (initially) to *high to full* (potentially)
-
-A fair exchange protocol or similar could be used to force operators to share
-their signature shares such that any individual node only learns enough shares
-to reconstruct the signature if all participants learn enough shares. In the
-greedy form of the attack the adversary only cares about maximizing its own
-profit, and thus it will prefer to reveal its signature share to others if not
-doing so would result in an indefinite stalemate.
-
-The cost of such a fair exchange as opposed to simple broadcast is lower group
-rewards for all participants due to slower submission of results, but
-participating in a suitable fair exchange protocol would be a dominant strategy.
-TODO: Whether fair exchange protocols that are resistant to a rushing adversary
-without a trusted third party are possible needs further investigation.
-
-
-=== Selfish signing - malicious
-
-A linchpin operator who can block others from completing the threshold
-signature selfishly submits the signature at such time _T~submit~_ that their
-own net reward
-_R~submitter~(T~submit~) + (m - 1) * R~group~(T~submit~)_
-is positive while everyone else suffers a late submission penalty:
-_R~group~(T~submit~) < 0_.
-
-This attack can be used to bootstrap dominance in the network.
-
-==== Attributability
-
-*Low*
-
-A signature submission by a node that hasn't broadcast its own signature share
-is evidence of selfish signing, but this can be circumvented by having the
-submitter node broadcast its share normally while the adversary's other nodes
-withhold theirs.
-
-As the signature is reconstructed from shares it is not possible to tell which
-nodes provided the shares for a given submission, and if the linchpin operator
-participates normally on one node its other nodes are indistinguishable from
-offline nodes.
-
-==== Viability
-
-*High* with sufficient adversary power;
-can be augmented by DoS capabilities
-
-The relationship of the derivative of the submitter's reward (grows over time)
-vs the group rewards (declines over time) influences the viability of this
-attack: an adversary with _m_ nodes can benefit absolutely when
-_dR~submitter~ / dT + (m - 1) * dR~group~ / dT > 0_
-; an adversary with 1 node will always benefit but is highly unlikely to become
-linchpin, while an adversary with a large number of controlled nodes is less
-likely to benefit but more likely to have linchpin status.
-
-In relative terms this attack is always profitable, and regardless of _m_ there
-always exists a _T~submit~_ such that
-_R~group~(T~submit~) < 0_
-but
-_R~submitter~(T~submit~) + (m - 1) * R~group~(T~submit~) > 0_
-and thus a sufficiently powerful and motivated adversary can use this attack to
-bleed out honest participants
-
-==== Mitigation
-
-*None* (initially) to *limited* (potentially)
-
-A malicious adversary may be willing to pay the opportunity costs of this attack
-and thus mitigations are more difficult to come by than with a greedy adversary.
-
-A fair exchange protocol does not work as well against a true linchpin
-adversary, as the adversary could still behave extortionately and deny everybody
-the beacon rewards unless it is allowed to become the submitter.
-
-In such a case the honest nodes could attempt to extort in return, but due to
-_m < h_ the marginal damage inflicted on the honest participants always exceeds
-the damage on the malicious party in the case of an indefinite stalemate.
-
-Additionally, identifying the presence of such an adversary is unlikely to be
-possible except via circumstantial evidence.
-
-
-=== Private key reveal
-
-The opposite of selfish signing; the misbehaving staker reveals their individual
-private key for the group's threshold signature with the intent to increase
-their reward as a non-submitter by letting other stakers calculate their
-signature share locally, and to let the staker be offline.
-
-==== Attributability
-
-*Full*
-
-The corresponding public key is known by all members in the same group.
-
-==== Viability
-
-*Low*, requires extremely specific conditions to be profitable
-
-If the cost of broadcast is high,
-the cost of operating a well-functioning node high,
-the reduction in group member rewards by increased time _dR~group~ / dT_ steep,
-the number of nodes _m_ controlled by _P~m~_ high,
-the probability of _P~m~_ otherwise getting submitter position low,
-the difference in submitter and group rewards _R~submitter~(T) - R~group~(T)_ low,
-the marginal improvement in submission time _T~submit~ - T'~submit~_ high,
-and the (probability of being caught) times the (impact on token price) low,
-it can be profitable to reveal one's individual signing key to other stakers so
-that _Sig~m~_ can be calculated locally without need for _P~m~_'s participation.
-
-==== Mitigation
-
-*None* (initially) to *full* (potentially)
-
-Relies on DKG individual public key attributability
-
-Any member in the group can prove this happened by publishing a tattletale
-message signed by the private key, containing the corresponding public key and
-its merkle path generated from the DKG results. On-chain would then verify the
-signature, and use the merkle path of the public key to verify that it belongs
-to the accused group member. If a valid accusation is published, the accuser
-would be rewarded and the misbehaving staker penalized.
diff --git a/docs-v1/random-beacon/pricing.adoc b/docs-v1/random-beacon/pricing.adoc
deleted file mode 100644
index 253be311bb..0000000000
--- a/docs-v1/random-beacon/pricing.adoc
+++ /dev/null
@@ -1,341 +0,0 @@
-:toc: macro
-
-= Pricing
-
-== Background
-
-The beacon needs to capture enough value to make it self-sufficient.
-It uses a simple method for pricing beacon entries
-that doesn't present easy exploitation opportunities.
-The pricing method avoids
-the known downfalls of previously considered, more complex, schemes,
-such as price discrimination being defeated by callback pooling.
-
-== Implementation
-
-=== Making requests
-
-A request begins with the query
-`entry_fee_estimate = estimate_fee(callback_gas_amount)`
-, which provides the customer with an estimated fee to use in the request.
-The fee estimate is only valid for the transaction it is called in,
-so the customer must make the request immediately after obtaining the estimate.
-Insufficient payment will lead to the request being rejected
-and the transaction reverted.
-
-To make a request after determining the applicable fee
-the customer must call the request method on the beacon,
-transferring enough currency to cover the fee:
-`request_entry.value(entry_fee_estimate)()`.
-
-If the customer wishes to receive the generated random number in a callback,
-they should also specify the _callback address_,
-_callback function_, and _callback gas amount_:
-`request_entry.value(entry_fee_estimate)(callback_address, callback_function, callback_gas)`.
-
-No new requests should be made
-while the beacon is already processing another request.
-Requests made while the beacon is busy will be rejected
-and the transaction reverted.
-
-=== Receiving a request
-
-A request sent to a non-busy beacon is checked for
-_request fee_ >= _entry fee estimate_ + _callback gas amount_ from the request.
-If the beacon is already serving an earlier request,
-it rejects any new requests and refunds the fee.
-
-A sufficiently funded request triggers the beacon
-to select the new signing group.
-The selected group is tasked with producing the new entry.
-
-The request is then set as the _pending request_
-with the following information:
-
-- the _requester address_
-
-- the _callback address_, _callback function_,
-and _callback gas amount_, if applicable
-
-- the _assigned signing group_{blank}footnote:[This is needed
-if changes to the active groups can be made
-while waiting for an entry.
-]
-
-- the _submission delay base time_ which equals
-the number of the block the request was received in,
-plus 1{blank}footnote:[The way of calculating rewards
-is inevitably prone to off-by-one errors _somewhere_
-and doing the incrementing at request time seems the simplest.
-]
-
-- the _request fee_ paid
-
-=== Serving a request
-
-==== Receiving submissions
-
-A valid entry created by a signing group is submitted by a
-member of the group called the _submitter_,
-before the _Submission deadline_.
-Submissions that fail verification are ignored.
-Repeat submissions for a request that has already been served
-are dropped immediately to minimize gas expenditure.
-
-If no valid entry has been received by the _submission deadline_
-a submission timeout can be called by anyone, as a result of which:
-
-- the failing group is terminated and its members slashed
-
-- a new signing group is assigned from the remaining active groups
-
-- the submission delay calculation is reset
-by setting the _submission delay base time_
-to the previous _submission deadline_.
-
-When a valid entry submission is received on-chain:
-
-- it is emitted in an event
-
-- the requester's callback is called if applicable
-
-- and fees, rewards and refunds are paid out
-
-==== Callback processing
-
-A callback is called using the callback gas amount as the maximum gas.
-If the callback gas amount is insufficient,
-callback execution is skipped
-and the rest of the relay entry submission code is processed as usual.
-
-_callback expenditure_ is calculated as,
-gas spent on call * minimum(gas price ceiling, actual gas price during transaction).
-
-The minimum of the gas price is included
-to protect the beacon and requester against malicious miner-submitters.
-
-Malicious miner-submitter attacks:
-
-- a miner-submitter can steal the surplus pool subsidy
-by placing an arbitrary gas price on the transaction
-that is higher than quoted.
-This will cause the requester refund to go negative.
-If the negative requester refund is added to the 1% surplus pool subsidy
-it can permit the miner-submitter to steal the subsidy.
-
-- a miner-submitter can steal the requesters refund
-by setting the gas price to the provided maximum.
-The requester is billed for the entire gas budget
-even if they really only spent a small fraction of it.
-
-A callback execution that uses more gas than specified in the request
-will run out of gas.
-A callback execution can cost more than was quoted and paid for
-only when the gas cost of the transaction exceeds the gas price ceiling.
-The submitter is intended to take the hit
-for submitting with a gas price that exceeds the gas price ceiling.
-
-=== Requester refund
-
-_requester refund = actual entry price - requester fee + 1% of request subsidy pool_
-
-_actual entry price = callback expenditure + entry base price_
-
-_entry base price = estimated gas price + profit margin + DKG contribution amortized over multiple entries + entry verification fee_
-
-_Group & Submitter reward = F (submission delay, submission delay base time)_
-
-If the sum of rewards paid out
-is < _profit margin + entry verification fee_,
-the difference is added to the _request subsidy pool_.
-
-The _DKG contribution_ is added to the _DKG fee pool_,
-and the state of the pool is checked.
-
-If the amount in the DKG fee pool equals or exceeds the _DKG cost estimate_,
-group creation and a new DKG may be triggered.
-
-=== Rewards
-
-A _base reward_ for each member of a signing group that produces an entry
-is specified in the system constants in the service contract and:
-
-_profit margin = base reward * group size_
-
-The exact rewards paid out to operators are based on the base reward
-but vary according to _submission delay_ and submitter position.
-
-To incentivize customers to request entries,
-any amount in excess of the _profit margin_
-is added to the beacons _request subsidy pool_
-
-==== Submitter reward
-_Submitter reward = F (submission delay, submission delay base time)_
-
-If the sum of rewards paid out
-is < _profit margin + entry verification fee_,
-the difference is added to the _request subsidy pool_.
-
-==== Group reward
-
-The group reward is paid to every member of the signing group,
-including the submitter, upon submission of a valid entry.
-
-The group reward equals the _base reward_
-multiplied by a _delay factor_
-equaling the fraction of time left by the submission deadline, squared:
-_group reward = base reward * delay factor_;
-_delay factor = (T~remaining~ / (T~deadline~ - T~begin~))^2^_;
-_T~remaining~ = T~deadline~ - T~received~_.
-
-The delay factor is counted
-from 1 in the first block a submission could be published in,
-to 0 in the deadline block which doesn't accept any more submissions.
-
-For example, assume the maximum time to submit is 20 blocks,
-the off-chain entry generation protocol takes 5 blocks
-and a request is made on block 1000.
-
-Block 1005 is the earliest block the submission could be published in:
-if published in this block the delay factor is 1.
-Block 1025 is the deadline block:
-no submissions are accepted and the delay factor is 0.
-
-If the entry is submitted in block 1009,
-the delay factor is:
-```
-((1025 - 1009) / (1025 - 1005))^2 = 0.8^2 = 0.64
-```
-Thus the _group reward = base reward * 0.64_,
-with the difference being the _delay penalty = base reward * (1 - 0.64)_.
-
-If the submission deadline is reached and the delay factor reaches 0,
-the entry submission fails and all group members are penalized.
-
-==== Submitter reward
-
-In addition to the _group reward_,
-the submitter is reimbursed for gas fees
-and receives an extra reward.
-
-The _submitter reward_ consists of:
-- _callback expenditure_ to cover the exact cost of the callback
-
-- the _entry verification fee_ to cover the cost of verifying the submission
-
-- 5% of the _delay penalties_ of the entire group
-
-Unlike the _callback allowance_,
-the entire _entry verification fee_ is paid to the submitter
-regardless of their gas expenditure.
-The submitter is free to spend less or more,
-keeping the surplus or paying the difference.
-This is to incentivize optimizing gas fees.
-
-To incentivize a race for the submitter position,
-the submitter receives:
-
- _delay penalty * group size * 0.05_ as an extra reward
-
-With realistic group sizes this is significant,
-but not high enough to render certain attacks profitable.
-If the group size is 100 and the delay factor is 0.64,
-the submitter receives an extra reward of:
-
-_base reward * 0.36 * 100 * 0.05 = base reward * 1.8_
-
-In this scenario the full submitter reward would be:
-
-_base reward * (1.8 + 0.64) + callback expenditure + entry verification fee_
-
-==== DKG submitter reimbursement
-How is the DKG submitter compensated?
-
-Getting to participate in a formed group is already valuable so there is no
-additional reward for a DKG result submitter. The only thing necessary is a gas
-cost reimbursement for the submitter.
-
-After the DKG result is submitted:
-
-_DKG result submission expenditure = minimum(gas price ceiling, actual gas price during transaction) * gas spent on call_
-
-The entire DKG result submission expenditure is returned to the submitter
-from the _DKG fee pool_ of the operator contract.
-
-The minimum of the gas price protects the beacon against malicious
-miner-submitters. If the submitter is also a miner, they can place any
-arbitrary gas price on the transaction. Without taking the minimum,
-miner-submitter would be able to steal from _DKG fee pool_ of the operator
-contract.
-
-Any surplus between the _DKG fee pool_ of the operator contract and
-the actual cost of DKG result submission is returned back to the service
-contract. In the case when the entire DKG fails, the unspent fee will be
-transferred back to the service contract upon the next DKG triggered by the
-service contract.
-
-The on-chain DKG result submission code needs to have all deterministic
-and time-bounded run paths that are independent of miner-controlled inputs.
-If the miner-submitter pays the gas price as set in the gas price ceiling, but
-tricks the contract into consuming twice the gas as normal, they will be able
-to get twice the reimbursement as well.
-
-=== Cost estimates
-
-==== Gas price ceiling
-
-A gas price ceiling is required
-to estimate the gas cost components.
-
-The critical feature of the gas price ceiling is
-that the ceiling price
-should be sufficient for getting beacon entries processed
-within the deadline under all circumstances.
-
-If actual gas prices rise to a level
-where gas price ceiling is insufficient
-for getting a transaction to be mined,
-and stays there for the duration of the entry submission window,
-the basic profit margin for the operators cannot be guaranteed.
-
-However, this does not imply that high gas prices
-would render the beacon inoperable.
-The submitter's extra reward incentivizes submitting
-even when the entry verification fee cannot cover the gas costs.
-In the extreme,
-avoiding the severe penalty for failure to produce an entry
-will incentivize group members to pay the gas prices
-up to the (theoretical) limit
-where gas for the entry submission transaction
-costs as much as the KEEP tokens at stake.
-
-==== DKG cost estimate
-
-The gas required for DKG should be calculated.
-DKG gas cost should include only DKG result submission.
-Ticket submission costs are covered
-by the expected return from getting into a signing group.
-Multiply DKG gas by gas price ceiling to get DKG cost estimate.
-Use a DKG frequency divider _d_ to set the group creation rate;
-once every _d_ entries on average.
-Divide DKG cost estimate by _d_ to get DKG contribution for each entry.
-
-The maximum DKG gas cost should be hardcoded in the operator contract.
-The service contract takes the highest applicable gas cost
-from all operator contracts being used
-and multiplies it by the gas price ceiling.
-
-As long as the gas price ceiling is sufficient
-to cover the immediate rise in gas fees during DKG execution
-the beacon is capable of generating new groups without requiring
-DKG result submitter to take a hit for submitting the result with
-a higher gas price.
-
-==== Entry verification fee
-
-Calculate gas required for verifying entry and associated support operations.
-The maximum entry verification gas cost
-are hardcoded in the operator contract.
-The service contract takes the highest applicable gas cost
-from all operator contracts being used
-and multiplies it by the gas price ceiling to get entry verification fee.
diff --git a/docs-v1/random-beacon/signing/index.adoc b/docs-v1/random-beacon/signing/index.adoc
deleted file mode 100644
index 6d44605197..0000000000
--- a/docs-v1/random-beacon/signing/index.adoc
+++ /dev/null
@@ -1,114 +0,0 @@
-= Random Beacon Signing
-
-== Terminology
-
-`P1`:: The generator point for the BLS elliptic curve
-
-`X_k`:: The group private key of `Group_k`
-
-`Y_k`:: The group public key: `Y_k = P1 * X_k`
-
-`Entry_e`:: The entry matching the entry identifier `e`
-
-`Input_e`:: The input for generating the new entry:
-`Entry_e = Input_e * X`
-
-`x_i`:: The individual private key of `P_i`
-
-`y_i`:: The individual public key of `P_i`: `y_i = P1 * x_i`
-
-`Share_i`:: The signature share by `P_i`: `Share_i = Input_e * x_i`
-
-`N`:: The number of members in a group
-
-`H`:: The number of members required for a honest majority
-
-== Signing group selection
-
-When a valid request has been received,
-the beacon begins the relay entry generation.
-
-The current block is recorded as the start block of the entry generation:
-
-`currentRequestStartBlock = block.number`
-
-The previous entry is hashed to produce the signing group selection seed.
-
-`seed = keccak256(previousEntry)`
-
-The signing group is selected by taking the value of the seed
-modulo the number of currently active groups,
-and selecting the corresponding active group:
-
-`selectedGroup = seed % numberOfGroups()`
-
-== Signature generation
-
-The selected group now has `relayEntryTimeout` blocks to submit the
-signature to `previousEntry`.
-
-=== Generating signature shares
-
-Each member `P_i` in `selectedGroup` calculates
-their signature share:
-`Share_i = previousEntry * x_i`.
-
-The generated shares are broadcast to the other members.
-The broadcast message contains
-the `Share_i` and the member index `i` of the sender `P_i`.
-
-`Message = (Share_i, i)`
-
-=== Verifying signature shares
-
-When `P_i` receives a signature share `Share_j` broadcast by `P_j`,
-the share can be verified by `blsVerify(Share_j, y_j, previousEntry)`.
-If `Share_j` is valid,
-`P_i` can use it for reconstructing the threshold signature.
-If `Share_j` is invalid, `P_i` must not use it for reconstructing the entry.
-
-=== Reconstructing the signature
-
-Once `P_i` has received at least `blsThreshold` valid shares,
-the entry can be reconstructed using Lagrange interpolation.
-
-----
-shares = validMessages.map(share)
-
-indices = validMessages.map(index)
-
-newEntry = lagrangeInterpolate(0, indices, shares)
-----
-
-== Output submission
-
-Member _P~submitter~_ of _Group~i~_ submits
-`newEntry = blsSign(previousEntry, X_i)`
-
-The beacon verifies that the submitted entry
-is a valid signature of the previous entry
-for the selected group's public key:
-
-`blsVerify(newEntry, previousEntry, Y_i)`
-
-If the submitted entry is valid,
-it is accepted as the current beacon entry _Entry~i~ = newEntry_.
-Reward _P~submitter~_ and other members of _Group~i~_
-according to the reward formula.
-
-If the submitted entry is invalid, it is rejected.
-
-== Entry timeout
-
-If a valid output is not submitted before block
-`timeoutBlock = currentRequestStartBlock + relayEntryTimeout + 1`,
-the entry generation for the selected group times out.
-From `timeoutBlock` onwards,
-no submissions by _Group~i~_ are accepted,
-and anyone can report the timeout by calling `reportRelayEntryTimeout()`.
-
-When the beacon receives a valid timeout report
-the previously selected group is terminated,
-with each member penalized for their (lack of) contribution to the failure.
-The beacon returns to the signing group selection
-with the failed group being removed from the group pool.
diff --git a/docs-v1/random-beacon/signing/sign.py b/docs-v1/random-beacon/signing/sign.py
deleted file mode 100644
index c39c585fa3..0000000000
--- a/docs-v1/random-beacon/signing/sign.py
+++ /dev/null
@@ -1,72 +0,0 @@
-class Request(NamedTuple):
- seedCommitment: Commitment[SeedValue]
- requesterPubkey: EcdsaPubkey
- stakeMultiplier: Float
- placedAt: Blockheight
- openTimeout: Blockheight
- previousOutput: BlsSignature
-
-def openCommitment(signingId, seed_i):
- request_i = Requests[signingId] # abort if no such request
- senderPubkey = getSenderPubkey()
- T_open = getCurrentBlockheight()
-
- # ignore commitment openings that arrive too late
- if T_open > request_i.openTimeout:
- abort()
-
- # ignore commitment openings by parties other than original requester
- if not request_i.requesterPubkey == senderPubkey:
- abort()
-
- # ignore invalid commitment openings
- if not request_i.seedCommitment == sha3(seed_i, senderPubkey):
- abort()
-
- Block_kPlus1 = getBlockByHeight(request_i.placedAt + 1)
- rseed_i = Block_kPlus1.blockhash
-
- Group_i = select(AllGroups, rseed_i)
- v_iMinus1 = request_i.previousOutput
- beaconInput = sha3(seed_i, rseed_i, v_iMinus1)
-
- outputWaiting = OpenOutput(
- startedAt = T_open,
- signingGroup = Group_i,
- signingInput = beaconInput
- )
-
- OutputInProgress[signingId] = outputWaiting
-
-
-def receiveOutput(signingId, outputSignature):
- outputWaiting = OutputInProgress[signingId] # abort if not found
- request_i = Requests[signingId]
-
- pubkey_Group_i = outputWaiting.signingGroup.groupPubkey
- input_i = outputWaiting.signingInput
-
- submitter = getSenderPubkey()
-
- signatureValid = blsVerify(
- outputSignature,
- input_i,
- pubkey_Group_i
- )
-
- if signatureValid:
- T_output = getCurrentBlockHeight() - outputWaiting.startedAt
-
- rewardGroup(
- submitter,
- group_i,
- T_output,
- request_i.stakeMultiplier
- )
-
- else:
- punish(
- submitter,
- INVALID_SIGNATURE_PENALTY * request_i.stakeMultiplier
- )
-
diff --git a/docs-v1/random-beacon/signing/terms.adoc b/docs-v1/random-beacon/signing/terms.adoc
deleted file mode 100644
index bf5700e91b..0000000000
--- a/docs-v1/random-beacon/signing/terms.adoc
+++ /dev/null
@@ -1 +0,0 @@
-= Terms used in beacon output generation
diff --git a/docs-v1/random-beacon/slashing.adoc b/docs-v1/random-beacon/slashing.adoc
deleted file mode 100644
index ca0e08000f..0000000000
--- a/docs-v1/random-beacon/slashing.adoc
+++ /dev/null
@@ -1,206 +0,0 @@
-:toc: macro
-:toclevels: 4
-
-= Misbehavior and punishments
-
-ifndef::yellowpaper[toc::[]]
-
-To incentivize correct behavior in the Keep network,
-misbehaving participants will be punished.
-In some situations,
-proving misbehavior requires cooperation from another participant,
-a _tattletale_.
-This coordination is incentivized by rewarding the _tattletale_
-by granting them a fraction of the tokens
-taken from the misbehaving participant.
-
-== Authorization
-
-_Operator contracts_ are authorized to impose penalties
-by stakers' _authorizers_.
-All stakers using the same _authorizer_
-share the set of authorized operator contracts.
-Once given, this authorization cannot be revoked by the authorizer.
-
-When an operator wishes to join a signing group
-the operator contract creating the group
-must be authorized by the operator's authorizer.
-Authorization is checked when an operator submits a ticket for validation.
-The operator contract queries the staking contract
-for the amount of stake available for it.
-If the operator contract is not authorized
-or the operator is otherwise ineligible for work selection,
-the staking contract will return that the operator has no available stake,
-leading to any submitted tickets being rejected.
-
-== Penalties
-
-When an operator's misbehavior is proven on-chain
-the operator contract calls the staking contract to punish the operator,
-specifying the type and magnitude of the punishment.
-The staking contract checks
-that the operator contract is authorized to punish the operator,
-and if true, applies the penalty according to its own rules.
-
-A penalty can be applied to one or more operators simultaneously.
-Each affected operator is penalized in the same way by the same amount.
-If the same address is listed multiple times
-among the operators to be punished,
-the punishment will be applied multiple times.
-
-=== Pure slashing
-
-When misbehavior is detected without third-party input,
-a _pure slashing_ penalty is applied.
-Pure slashing means that the staking contract
-subtracts the applicable penalty from the operator's stake
-and burns tokens equal to the penalty amount.
-If the operator doesn't have enough stake for the punishment
-(e.g. because it has been punished earlier),
-the punishment is equal to the remaining stake.
-
-=== Seizing
-
-When a tattletale proves another operator's misbehavior,
-a fraction of the penalty amount is _seized_ and transferred to the tattletale,
-while the rest is burned.
-
-If the full amount is transferred to the tattletale,
-it can be exploited to transfer staked tokens
-without the normal constraints.
-To reduce the effectiveness of this "tattletale transfer",
-the seized amount is limited to a maximum of 5% of the entire penalty.
-The tattletale reward can be set to any value
-between 0 and the maximum of 5% of the penalty.
-
-To apply a seizing penalty,
-the operator contract includes the tattletale operator's address in the call.
-The staking contract subtracts the applicable penalty from the operator's stake
-and transfers the reward to the tattletale's _beneficiary_ address.
-The remainder is burned.
-
-=== Penalty amounts
-
-In later versions,
-penalties for misbehavior can be adjusted
-to match the severity of the misbehavior.
-However, initially the penalty for misbehaving in the random beacon
-will equal the minimum stake required to join a signing group.
-
-== Interfaces
-
-=== Staking contract: slashing
-
-`slash(tokens amount, address[] misbehavers)`::
-
-Slash each operator in the list `misbehavers`
-by the specified amount
-(or their remaining stake, whichever is lower).
-+
-For each `misbehaver` in `misbehavers`,
-perform the following:
-+
-. Check that the caller is authorized to slash the operator:
-`isAuthorized(msg.sender, misbehaver.authorizer) == true`.
-. Determine the applicable punishment for the operator:
-`thisPenalty = min(amount, misbehaver.stake)`.
-. Subtract the punishment from the operator's stake
-and add it to the total to be burned:
-`misbehaver.stake -= thisPenalty; totalPenalty += thisPenalty`.
-+
-Finally, burn an amount of tokens equal to the slashed total:
-`tokenContract.burn(totalPenalty)`.
-
-`seize(tokens amount, float rewardMultiplier, address tattletale, address[] misbehavers)`::
-
-Punish each operator in the list `misbehavers`
-by the specified amount or their remaining stake.
-Reward the `tattletale` by an amount between 0 and the maximum reward,
-determined by the `rewardMultiplier` argument:
-if `rewardMultiplier` is greater than `0` and at most `1`,
-multiply the highest allowed tattletale reward by `rewardMultiplier`.
-Otherwise reject the call for an invalid reward multiplier.
-+
-For each `misbehaver` in `misbehavers`,
-calculate and apply the appropriate penalty
-and track the total as in `slash()`.
-+
-Finally, determine the tattletale reward:
-`reward = totalPenalty * 0.05 * rewardMultiplier`.
-Transfer the reward to the tattletale's _Beneficiary_
-and burn the rest of the penalty:
-`tokenContract.burn(totalPenalty - reward)`.
-
-=== Staking contract: authorizations
-
-`authorize(address op_contract)`::
-
-Authorize `op_contract`.
-Operators using `msg.sender` as their authorizer
-may now join operations on `op_contract`
-and `op_contract` may slash their stakes.
-
-`isAuthorized(address op_contract, address authorizer) -> bool`::
-
-Check if the authorizer `authorizer` has authorized `op_contract`
-to apply punishments on operators using `authorizer` as their authorizer.
-
-`eligibleStake(address operator) -> uint`::
-
-Return the number of staked tokens available for the calling contract.
-Includes an authorization check `isAuthorized(msg.sender, operator.authorizer)`
-and other checks on the operator's eligibility for work selection.
-
-=== Token contract
-
-`burn(amount sum)`::
-
-Any address that holds tokens can call `burn(amount sum)`
-to burn `sum` tokens, limited by tokens held by the address.
-
-== Punishable misbehavior
-
-=== Failure to sign an entry
-
-If a signing group is tasked with producing a beacon entry,
-but fails to submit a valid entry within the allotted deadline,
-each member in the group is punished by _seizing_
-and the group itself will be terminated.
-
-The punishment is triggered by calling `reportRelayEntryTimeout()`
-once the deadline has been reached.
-The submitter of the trigger transaction will be treated as the _tattletale_,
-but the tattletale reward will be limited
-to `min(1, 20 / group_size)` of the maximum,
-or effectively the minimum stake of a single member.
-This is to prevent actors in a lynchpin position
-from profitably stealing other stakers' funds.
-
-=== Unauthorized use of group signing key
-
-If the group signing key of a signing group has been leaked,
-it can be proven by using the key to sign the address of the group
-and calling `reportUnauthorizedSigning()`.
-
-If the signature is valid for the public key of the signing group,
-it proves that the key has been used without authorization.
-Each member of the signing group is punished by _seizing_
-and the group is terminated.
-The submitter of the trigger transaction
-receives the maximum tattletale reward.
-
-////
-=== Disqualification in DKG
-
-If an operator misbehaves during DKG,
-and is included among the disqualified operators
-when a valid DKG result is submitted,
-the misbehaving operator is punished by _seizing_
-and removed from the created group.
-The submitter of the DKG result
-receives the maximum tattletale reward.
-
-It should be noted that a dishonest majority could punish honest operators.
-However, such behavior can be proven off-chain
-by presenting a DKG transcript conflicting with the accepted result.
-////
diff --git a/docs-v1/random-beacon/staking/index.adoc b/docs-v1/random-beacon/staking/index.adoc
deleted file mode 100644
index e0f2fa43ef..0000000000
--- a/docs-v1/random-beacon/staking/index.adoc
+++ /dev/null
@@ -1,529 +0,0 @@
-= Staking
-
-The Keep network uses staking of tokens to enforce correct behavior.
-
-== Basic description
-
-Anyone with tokens can stake them,
-setting them aside as collateral for network operations.
-Staked tokens are delegated to an _operator_ address
-who performs work for _operator contracts_.
-_Operators_ can earn rewards from contributing to the network,
-but if they misbehave their collateral can be taken away
-(_stake slashing_) as punishment.
-
-=== Stakers and roles
-
-A token owner may wish to stake in a variety of different ways,
-for security or efficiency reasons.
-To support different ways of staking,
-the network uses a single abstraction of a _staker_
-comprised of multiple separate _roles_:
-
-owner::
-Provides the tokens for the staker
-
-operator::
-Handles the day-to-day participation in the network operations
-
-beneficiary::
-Collects any rewards earned by the staker
-
-authorizer::
-Authorizes contracts to protect against buggy or compromised upgrades
-
-The different roles can all be performed by the same address;
-they may be divided between different addresses controlled by the same person;
-or they may be different parties entirely,
-executing a sophisticated scheme of cold storage and third-party delegation.
-As far as the network is concerned,
-any of these arrangements simply forms a _staker_.
-
-staker::
-An abstraction representing the _owner_, _operator_, _beneficiary_ and _authorizer_
-each performing their respective roles.
-
-Stakers are identified by their operator address.
-
-=== Initiating staking
-
-Staking is initiated by the _owner_ choosing the amount of tokens to stake,
-and the _operator_, _beneficiary_ and _authorizer_ addresses.
-The owner then authorizes the _staking contract_ to claim a number of tokens,
-and calls the staking contract to stake the tokens.
-The _staking contract_ processes the call,
-claims the tokens to itself,
-and records the information.
-The addresses of the roles cannot be changed after delegation.
-
-=== Contract authorization
-
-Before the staker can participate in the network,
-the _authorizer_ must _authorize_ each _operator contract_
-the staker wishes to use.
-It is necessary to introduce new functionality and to upgrade old contracts,
-but buggy or malicious _operator contracts_ could be used
-to steal or destroy tokens by _slashing_ well-behaved stakers.
-The requirement for _authorization_ ensures that the owner's tokens are safe
-even if a contract upgrade is compromised,
-as long as the _authorizer_ denies authorization to such contracts.
-
-Once a contract has been authorized,
-the authorization cannot be revoked.
-
-=== Operation
-
-The _operator_ provides _services_ in the network
-by following the protocols of authorized _operator contracts_.
-
-Any number of operations may be active at once
-regardless of the _staked amount_.
-
-==== Rewards
-
-Stakers that provide services in the network
-will be rewarded at certain points.
-Rewards may be either tokens or the currency used to pay for network services.
-Rewards earned by a staker will be sent to the staker's _beneficiary_ address.
-
-=== Slashing
-
-If a staker violates the protocol of an operation
-in a way which can be proven on-chain,
-they will be penalized by having their stakes _slashed_.
-
-If a staker has joined multiple operations at once,
-they may accrue more punishments than their stake can cover.
-If a staker's remaining stake falls to zero,
-the staker is terminated and may not continue any operations.
-Any remaining penalties are nullified.
-
-==== Tattletales
-
-Some misbehavior cannot be caught by a contract alone
-and requires the cooperation of a third party _tattletale_.
-If a _tattletale_ presents proof of misbehavior by a staker,
-a part of the penalty will be awarded to the tattletale
-as a _tattletale reward_.
-
-=== Unstaking
-
-When staking, the tokens used as collateral are locked
-until the staker announces their intention to stop staking,
-and for a period of time afterwards.
-The purpose of this _unstaking period_ is to give operations time to finish
-before the collateral can be moved away.
-No new operations can be started or joined within the _unstaking period_
-but the staker is required to continue participating
-in any unfinished operations.
-
-== Details
-
-=== Roles
-
-The staker is an abstraction comprising of four different roles,
-each with a clear scope of responsibility.
-The initial design included only the roles of the owner, operator and beneficiary;
-the authorizer was added to take full advantage of the upgrade security plan.
-
-==== Owner
-
-The owner makes the decision to stake,
-provides the tokens for the staker,
-and chooses the addresses for the other roles.
-The owner can initiate unstaking and reclaim tokens,
-but these can also be performed by the operator.
-
-The role of the owner is designed to facilitate cold storage
-by minimizing the interaction necessary for staking.
-Initiating staking is the only operation
-where the owner's keys are absolutely required.
-
-==== Operator
-
-The operator address is tasked with participation in network operations,
-and represents the staker in most circumstances.
-
-Rewards and punishments are based solely on the operator's actions,
-and the operator can not only cause opportunity costs
-but can also lose the entire stake and possibly steal a fraction of it
-using only contracts functioning as intended.
-If the operator is a different party from the owner,
-a high level of trust is necessary.
-
-In addition to participating in the network
-via the authorized operator contracts,
-the operator can also initiate undelegation.
-
-==== Beneficiary
-
-The beneficiary is an entirely passive role.
-Rewards of tokens or currency are simply sent to the beneficiary address
-by the staking contract.
-
-The beneficiary role is separate from the owner and operator
-to provide flexibility in how to receive and use rewards
-without interfering with the owner's cold storage
-or the possible contractual relationship between the owner and operator.
-
-==== Authorizer
-
-Because slashing stakes requires arbitrary access to stakers' accounts,
-explicit authorization is required
-for each operator contract before it may penalize stakers.
-
-The upgrade security plan is designed
-to limit the impact of upgrade key compromise
-and to provide a graceful recovery route
-while minimizing the impact to the rest of the network.
-The explicit authorization requirement prevents a compromised contract
-from stealing stakers' funds by exploiting the punishment interface.
-Instead, compromise of both the authorizer and the contract is required.
-
-As a further security measure,
-the authorizer can only authorize pre-approved contracts
-from a list maintained by the governance structure of the network.
-This ensures that the authorizer cannot do damage
-in the absence of further compromise,
-except by withholding desired authorizations.
-
-The authorizer role is separated from the owner and operator
-to facilitate cold storage for the former
-and to reduce the necessary privileges of the latter.
-
-If the owner were required to authorize each new contract and upgrade,
-it would present an unnecessary hindrance to effective cold storage schemes.
-Due to the two-factor nature of the authorizer keys,
-the same level of protection is not necessarily required.
-
-On the other hand, separating the authorizer from the operator
-reduces the latter's ability to profit from damaging the owner's interests.
-While even the operator has the ability
-to lose or steal the owner's tokens,
-it is restricted by the opportunities provided by the authorized contracts.
-Using the tattletale mechanism to transfer tokens is inefficient,
-but a compromised contract would not be subject to the same restrictions
-and could be used to transfer all of the staker's tokens to the attacker.
-
-===== Third party delegation
-
-The role of the authorizer can be delegated to a third party,
-and it is expected that many would do so.
-
-Most owners and operators are unlikely to scrutinize each contract,
-or even to have the ability to do so effectively.
-Providing a convenient way to express one's choice to trust a third party
-would make centralization of such trust visible.
-
-A downside of convenient delegation is that requiring individual authorizations
-provides another source of friction and human judgment
-between compromise of single points of failure and actual loss of staker funds.
-An owner can avoid this fate
-by not assigning a third party as the authorizer address.
-
-=== Staking contract
-
-The staking contract records two time (blockheight) fields for each operator:
-the block the operator was created,
-and the block undelegating began.
-
-Operators can be:
-
-- _non-existent_
-- _not ready_ for work selection because they were created too recently
-- _active_ and eligible for work selection
-- _winding down_ and ineligible for work selection but finishing earlier work
-- _finished_ undelegation so the owner can recover their tokens
-
-Using the systemwide constant _undelegation period_,
-the operator's _status_ can be determined
-from the creation and undelegation blocks.
-
-Operators are uniquely identified by their address
-and operator addresses cannot be reused,
-even after returning the tokens to the owner.
-
-To reduce the impact of transaction reordering,
-both delegating and undelegating take effect on the next block
-after the block the transaction is processed in.
-
-==== Parameters
-
-===== Operator initialization period
-
-E.g. 50,000 (roughly 6 days)
-
-To avoid certain attacks on work selection,
-recently created operators must wait for a specific period of time
-before being eligible for work selection.
-This waiting period must be greater than the highest permissible time
-between the making of a beacon entry request
-and the request being served.
-In the ideal case, multiple entries would be requested and generated
-within the initialization period.
-
-If the initialization period is insufficiently long,
-the pseudorandom work selection process can be subverted
-by creating operators whose identifiers (addresses)
-are calculated to yield advantageous outputs in the selection function.
-This can let the adversary control the majority in the new signing group.
-
-If the new group is in line to sign the next entry,
-the adversary could choose the group's private key
-so that the following entry also gets signed
-by a group controlled by the same adversary.
-With sufficient calculation capability,
-this can be repeated _n_ times at the cost of roughly _O(k^n^)_ calculations
-where _k_ equals the number of active groups
-divided by the number of active adversary-controlled groups.
-If another signing group is created within this time,
-it can be similarly controlled.
-This can eventually lead to the adversary controlling the entire network.
-
-With the initialization period,
-the adversary has to create the operators in advance
-long before they become eligible for work selection.
-Thus the adversary has to be able to predict each entry
-generated during the initialization period.
-With an unreasonably powerful adversary
-that can arbitrarily frontrun 50% of all entries,
-generating _n_ entries within the initialization period
-provides _2^n^_ security against this attack.
-
-===== Undelegation period
-
-E.g. 200,000 ~ 800,000 (roughly 1 to 3 months)
-
-The staking contract guarantees that an undelegated operator's stakes
-will stay locked for a number of blocks after undelegation,
-and thus available as collateral for any work the operator is engaged in.
-
-==== Operator data
-
-----
-mapping(address => Operator) operators;
-
-struct Operator {
- uint128 stakedAmount;
- uint64 createdAt;
- uint64 undelegatedAt;
- address owner;
- address beneficiary;
- address authorizer;
-}
-----
-
-Each operator stores the addresses of its owner, beneficiary and authorizer,
-the amount of tokens delegated to the operator,
-the block it was created at,
-and the block it was undelegated at if applicable.
-
-==== Operator status
-
-----
-enum Status { NonExistent, NotReady, Active, WindingDown, Finished }
-
-operatorStatus(address operator) -> Status
-----
-
-An operator's status determines what actions are available
-for the operator and the owner the delegated tokens.
-
-===== Non-existent
-
-The operator doesn't exist.
-
-`operators[operator] == nil`
-
-===== Not ready
-
-The operator has been created in the same block the query was performed in.
-The operator is ineligible for work selection.
-
-An operator is `NotReady`
-if the current block is equal or less than
-the creation block plus the initialization period.
-
-`block.number =< operator.createdAt + initializationPeriod`
-
-===== Active
-
-The owner has delegated staked tokens to the operator,
-and the operator is eligible for work selection.
-
-An operator is `Active`
-if the current block is greater than
-the creation block plus initialization period,
-and the undelegation block is either 0 or equal or greater than the current block.
-
-`block.number > operator.createdAt + initializationPeriod && (block.number =< operator.undelegatedAt || operator.undelegatedAt == 0)`
-
-===== Winding down
-
-The operator has been undelegated and is not eligible for work selection,
-and the operator is finishing any work they were selected for earlier.
-The operator's backing tokens continue to be locked as collateral.
-
-An operator is `WindingDown`
-if the current block is greater than the undelegation block,
-but at most the undelegation block plus the undelegation period.
-
-`operator.undelegatedAt < block.number =< (operator.undelegatedAt + undelegationPeriod)`
-
-===== Finished
-
-Undelegating the operator has finished.
-The backing tokens are unlocked and can be returned to the owner.
-
-An operator is `Finished` if the current block is greater than
-the undelegation block plus the undelegation period.
-
-`block.number > operator.undelegatedAt + undelegationPeriod`
-
-==== Work selection eligibility
-
-`eligibleStake(address operator, uint block) -> uint`
-
-Operators are eligible for work selection
-based on their status in the block the work selection started in.
-In some situations an operator's status may have changed
-after work selection started,
-but before the operator contract queries it.
-For these cases the staking contract must provide a way to determine
-the operator's eligibility for work selection that started in an earlier block.
-
-It is the responsibility of each operator contract
-to query operator eligibility with the correct block number.
-Failure to use the correct block leads to minor manipulation opportunities.
-For example, querying an operator's eligibility
-on the current block when they submit a ticket
-means that an ineligible operator whose initialization period is almost over
-could wait to submit their ticket
-until they become eligible for work selection.
-
-To make determining an operator's eligibility for work selection
-simpler and cheaper,
-the staking contract must provide the `eligibleStake()` function
-which returns the number of KEEP tokens available for use as collateral.
-
-When calling `eligibleStake()`,
-the staking contract assumes `msg.sender` is an operator contract.
-`eligibleStake()` does not return meaningful results
-when called by an address that doesn't correspond to an operator contract.
-If the `operator` is ineligible for work selection on `msg.sender`,
-`eligibleStake()` returns `0`.
-Otherwise `eligibleStake()` returns `operator.stakedAmount`.
-
-----
-operatorExists = operators[operator] != nil
-
-senderAuthorized = authorized[operator.authorizer][msg.sender] == True
-
-operatorReady = block > operator.createdAt + initializationPeriod
-
-notUndelegated = block =< operator.undelegatedAt || operator.undelegatedAt == 0
-
-if operatorExists && senderAuthorized && operatorReady && notUndelegated:
- return operator.stakedAmount
-else:
- return 0
-----
-
-==== Actions
-
-===== Staking
-
-`stake(uint amount, address operator, address beneficiary, address authorizer)`
-
-Staking tokens delegates them to the operator,
-who can then use them as collateral for performing work.
-Staking is performed by the owner of the tokens,
-who must have authorized the staking contract
-to transfer `amount` KEEP to itself
-(e.g. via `approveAndCall()`).
-
-`token.allowance(msg.sender, stakingContract) >= amount`
-
-The nominated operator must not already exist.
-
-`operators[operator] == nil`
-
-The staking contract transfers `amount` KEEP from `msg.sender` to itself,
-and creates a stake delegation relationship,
-with the operator becoming `Active` in the next block.
-
-----
-operators[operator] = Operator {
- stakedAmount = amount;
- createdAt = block.number;
- undelegatedAt = 0;
- owner = msg.sender;
- beneficiary = beneficiary;
- authorizer = authorizer;
-}
-----
-
-===== Cancelling staking
-
-`cancelStake(address operator)`
-
-The owner can cancel staking within the operator initialization period
-without being subjected to the token lockup for the undelegation period.
-This can be used to undo mistaken delegation to the wrong operator address.
-
-`msg.sender == operator.owner`
-
-`block.number =< operator.createdAt + initializationPeriod`
-
-If staking is cancelled,
-the staked tokens are immediately returned to the owner,
-and the undelegation time is set to the present.
-
-`operator.stakedAmount = 0`
-
-`operator.undelegatedAt = block.number`
-
-===== Undelegating
-
-`undelegate(address operator)`
-
-Undelegating sets the operator to `WindingDown` status
-so that the backing tokens can later be recovered by the owner.
-Undelegating can be performed by either the owner or the operator.
-
-`msg.sender == (operator || operator.owner)`
-
-Undelegating can only be performed on a currently active operator.
-
-`operatorStatus(operator) == Active`
-
-The staking contract sets the undelegation block of the operator
-to equal the current block,
-making the operator ineligible for any work selection in the future.
-Work selection performed earlier in the same block shall proceed as normal.
-
-`operator.undelegatedAt = block.number`
-
-===== Recovering tokens
-
-`recoverStake(address operator) -> uint`
-
-Recovering staked tokens transfers them back to the owner.
-Recovering tokens can only be performed by the owner,
-when the operator is finished undelegating.
-
-`msg.sender == operator.owner`
-
-`operatorStatus(operator) == Finished`
-
-The staking contract sets the staked amount of the operator to zero,
-and transfers the previously delegated tokens (or however much was remaining)
-back to the owner.
-
-`operator.stakedAmount = 0`
-
-The staking contract may additionally clean up
-the owner, beneficiary and authorizer addresses for the gas refund.
-However, the staking contract must not delete
-the creation and undelegation times,
-as this would enable reuse of the same operator address.
diff --git a/docs-v1/random-beacon/staking/notes.adoc b/docs-v1/random-beacon/staking/notes.adoc
deleted file mode 100644
index b29793c4ca..0000000000
--- a/docs-v1/random-beacon/staking/notes.adoc
+++ /dev/null
@@ -1,350 +0,0 @@
-= Staking
-
-Notes and speculation
-
-== Minimum stake
-
-From the Ethereum rich list at etherscan.io:
-
-7,000 accounts have at least 1/100,000 of the total supply each
-1,000 accounts have at least 1/10,000
-150 accounts have at least 1/1,000
-5 accounts have at least 1/100
-
-From btc.com rich list:
-
-100 accounts with 10,000+ (1/1,750)
-2,000 accounts with 1,000+ (1/17,500)
-15,000 accounts with 100+ (1/175,000)
-150,000 accounts with 10+ (1/1,750,000)
-
-Non-trivial stake requirements in other projects:
-
-Ethereum (Casper docs): 1,000 ETH deposit (1/100,000)
-Ethereum (speculation of eventual minimum): 32 ETH (1/3,000,000)
-Dash: 1,000 Dash (1/8,500)
-Cardano: 10,000 ADA (1/4,500,000)
-Tezos (masternode): 10,000 XTZ (1/80,000)
-Decred: ~110 (1/80,000)
-
-Initial suggestion: 10,000 KEEP or 1/100,000 of the total supply
-
-.Market cap vs. minimum stake
-|===
-|Market cap |Minimum stake
-
-|$10M |$100
-|$100M |$1,000
-|$1,000M |$10,000
-|$10,000M |$100,000
-|===
-== Authorizations
-
-Can't revoke authorizations:
-naively implemented, this functionality would enable evading penalties.
-It could be made to work
-by keeping track of when a staker actually is active in a contract,
-but this would impose significant storage burdens.
-
-== Token grants
-
-* a specific amount of tokens
-* for a specific address
-* locked up for a specific time period
-* vesting over time, unlocking parts of the grant
-* may have a cliff, so tokens only start to unlock after a certain point
-* may be revocable
-
-Most of the issues with token grants concern conflicts of interest
-between the _grant creator_ and the _grant recipient_,
-and the _recipient's_ ability to subvert the goals of the _creator_.
-If the creator and recipient are considered to be a single actor
-as far as the rest of the network is concerned,
-any such conflicts would simply manifest
-as seemingly irrational behavior from the actor as whole.
-
-However, given that the Keep org is the most significant grant creator
-and all initial tokens would be given out as grants,
-the practical effects of the grant mechanism are significant.
-
-=== Grant features
-
-Currently planned for 2 years or roughly 100 weeks
-
-If minimum stake is set at 10,000 and stake-ahead at 2 weeks,
-the minimum to begin staking right away would be 500,000
-or 1/2,000 of the supply
-
-=== Tattletale transfer
-
-(T-transfer for convenience)
-
-Misbehave deliberately in a way which entitles a tattletale to large rewards,
-collect rewards on another account you control.
-
-_transfer_efficiency = tattletale_reward / misbehavior_penalty_
-
-When you know your grant would be revoked,
-t-transfer may act as a way to secure a fraction
-_grant * transfer_efficiency_ of the grant.
-
-When you expect the future value of _grant_ to be less than
-_transfer_efficiency * grant_ right now,
-t-transfer may enable premature seizing of the value.
-
-The practicality of t-transfer depends on the efficiency,
-dictated by how contracts use slashed stakes.
-If the seized collateral or a significant fraction
-is transferred to an address the adversary can control,
-t-transfer is highly viable.
-If the seized collateral is distributed widely
-in a way that is difficult to bias,
-eg. in proportion to stakers' legitimate earnings from the contract,
-the efficiency plummets.
-
-biased distribution::
-An algorithm for distributing slashed stakes is _biased_
-if adversary _A_ with _adversary stake_ tokens
-can give it some input _i_ that is not publicly available to all stakers,
-and thus change the expected distribution so that _A_ receives more than
-_(adversary stake / total staked) * slashed amount_.
-
-unbiased distribution::
-An algorithm for distributing slashed stakes has an _unbiased distribution_
-when the expected amount of tokens received by any adversary
-with _adversary stake_ tokens staked
-is equal to _slashed amount * (adversary stake / total staked)_
-regardless of the adversary's input.
-
-[NOTE]
-.T-transfer efficiency conjecture
-====
-The minimum t-transfer efficiency
-for an adversary controlling _adversary_fraction_ of stakers
-is conjectured equal to _adversary_fraction_.
-
-This _unbiased distribution_ may be achieved in different ways:
-by eg. simply transferring the tokens
-to a random address weighted by stakes;
-or by increasing all future rewards from the contract
-by a small amount.
-
-Any method that attempts to change this distribution
-is subject to manipulation by the adversary "playing both sides".
-
-For example, gifting the tokens to a random staker, non-weighted,
-disproportionately rewards blitzpantsing.
-The adversary, knowing in advance that they would be penalized,
-can then prepare for this.
-Similarly, the tattletale reward itself is such a bias,
-subject to advance preparation on the basis of privileged information.
-
-Such a biasing method is conjenctured to be possible
-for every biased distribution of slashed tokens.
-====
-
-=== Slashing methods
-
-==== Simple slashing
-
-The simplest method for slashing
-simply transfers the impacted tokens to the slashing contract.
-This gives the contract full freedom
-to distribute the tokens immediately
-or keep them for future rewards.
-
-The simple method of slashing does not enable
-the enforcement of any relevant invariants
-in the staking contract itself,
-and thus all staked tokens are potentially subject to t-transfer.
-
-==== Simple variant
-
-A variant of the simple method would use two different slashing functions:
-`slash` and `slashAndReward`.
-`slash` would be a straightforward seizure of collateral
-followed by distributing the tokens in an unbiased way,
-while `slashAndReward` would nominate a tattletale staker
-to receive a specified fraction of the seized tokens
-and keep the rest in the functionality contract for unbiased distribution.
-
-The simple variant allows more sophisticated discrimination
-between stakes that may be subject to efficient t-transfer
-and stakes that are distributed evenly.
-Even in this case, it is both necessary
-and impossible within the staking contract
-to ensure that the contract actually implements the unbiased distribution.
-
-==== Limited-bias slashing
-
-A more sophisticated variant could be constructed
-using a separate contract for the desired unbiased distribution scheme.
-In this case it would be possible
-to determine the characteristics of the reward scheme,
-and use unbiased distributions safely
-where biased distributions pose t-transfer threats.
-
-The functionality contract would use the functions
-`slashAndSeize` and `slashAndDistribute` for the collateral.
-With `slashAndSeize` the tokens would be subject to arbitrary distribution,
-while `slashAndDistribute` would grant them in an approved unbiased way.
-Thus `slashAndDistribute` could be called without limits
-on tokens subject to grants,
-and the problem would be limited to `slashAndSeize`.
-
-If the creator of the grant approves in advance
-the contracts `slashAndDistribute` may be used with,
-determining the unbiasedness of any particular reward distribution scheme
-is externalized onto an off-chain party
-whose incentives obviously maximally align with those of the grant creator.
-
-It may be recommendable to always call `slashAndSeize` with `slashAndDistribute`
-to provide a ceiling on the maximum achievable t-transfer efficiency.
-If _t_ tokens are slashed,
-with _t * B_ going to `slashAndSeize`
-and _t * (1 - B)_ going to `slashAndDistribute`,
-the distribution may be called a _partially biased distribution_
-with a bias ceiling of _B_,
-or a _B-biased distribution_ (eg. "50% biased distribution").
-
-If a cap on reward distribution bias is enforced by the grant creator,
-so that only _partially biased distributions_ are allowed,
-requiring that _0 =< B =< maximum allowed bias < 1_,
-a known minimum resistance to t-transfer can be ensured.
-The grant amount could be staked with _B * minimum stake_ being vested tokens
-and _(1 - B) * minimum stake_ being unvested tokens.
-
-=== False stake
-
-If Mallory has a grant and is expecting the grant to be revoked,
-tokens that would be unvested at the time of revocation are not efficient stake;
-Mallory has nothing to lose from expending such tokens
-as stakes for misbehavior that gives any personal advantage otherwise.
-
-If Mallory is not expecting the grant to be revoked,
-the time value of money and future expectations on token value
-can still reduce the effective value of the locked-up tokens.
-
-In the case of non-revocable grants,
-it would be possible to reduce the effect of future discounting
-by requiring more tokens if the tokens vest at a time far in the future.
-
-=== Staking ahead
-
-Withdrawing staked tokens requires waiting the _unstaking period_.
-If staker _S_ is choosing between unstaking and continuing at time _T_,
-the amount of unlocked tokens they could withdraw at the earliest possible time
-is _UnlockedTokensAt(T + T~unstake~)_.
-Thus it may be safe to use tokens
-that are locked at the present time but would vest within the unstaking period
-as collateral.
-
-If minimum stake is 10,000 KEEP or 1/100,000 of the total supply,
-and grants last 2 years,
-the de facto minimum stake to begin staking immediately
-is determined by _minimum stake * (100 weeks / unstaking period)_
-
-.Unstaking period vs. de facto minimum stake at various market caps
-|===
-|Waiting period |$10M |$100M |$1,000M
-
-|1 week |$10k |$100k |$1M
-|2 weeks |$5k |$50k |$500k
-|4 weeks |$2,500 |$25k |$250k
-|10 weeks |$1,000 |$10k |$100k
-|25 weeks |$400 |$4k |$40k
-|===
-
-=== Grant-compatible staking
-
-Instead of staking contract, split the responsibilities:
-
-==== Staking proxy
-
-The staking proxy is not called directly;
-instead an entry is created
-when one of the staking contracts has a staking event.
-
-staker[staker_id] -> backend::
-The contract addresses of the rules each staker operates under
-
-initialize(staker_id)::
-
-
-remove(staker_id)::
-Remove the backend address entry of the specified staker
-
-==== Staking backend
-
-A contract that can provide the required interface to the staking proxy:
-
-weight(staker_id) -> int::
-Returns the staker weight of the specified staker.
-
-operator(staker_id) -> address::
-Returns the address which has _operator_ authority for the specified staker.
-
-beneficiary(staker_id) -> address::
-Returns the address which has _beneficiary_ authority for the specified staker.
-
-overseer(staker_id) -> address::
-Returns the address which has _overseer_ authority for the specified staker.
-
-reward(staker_id, amount)::
-Rewards the staker with tokens or currency.
-
-slash(staker_id, amount)::
-Seizes _amount_ tokens from the staker and gives them to the calling contract.
-If the staker state is `Active`
-this method is required to transfer the tokens to the calling contract.
-Calling `slash` on an `Unstaking` staker is backend-specific.
-
-===== Backend: free stakes
-
-
-* `amount` of staked tokens
-* `state` of the staker (`Active` or `Unstaking`)
-* `since` time of last change (staking or unstaking)
-* `owner` of the tokens
-* `operator` address performing operations
-* `beneficiary` address to send rewards to
-* `overseer` address to determine authorized contracts
-
-stake(amount, operator, beneficiary, overseer)::
-Initiate staking by specifying the addresses of the other roles
-and transferring at least _minimum stake_ tokens to the contract
-+
-The caller is designated as the owner
-+
-May be called by any address with at least _minimum stake_ tokens
-
-unstake(staker_id)::
-Initiate unstaking, start the unstaking period
-and stop the staker from joining any new operations
-+
-May be called by either the owner or the operator of the staker
-
-return_tokens(staker_id)::
-Terminate a staker that has finished unstaking
-and return the staked tokens to the owner
-+
-May be called by either the owner or the operator of the staker
-
-reward(staker_id, amount)::
-Reward a staker for correct operation
-and transfer currency or tokens to its beneficiary address
-+
-May be called by a functionality contract
-
-slash(staker_id, amount)::
-Punish a staker for misbehavior and seize some of its tokens
-+
-The seized tokens may be used in whathever way is specified by the contract
-+
-May be called by a functionality contract authorized by the staker's overseer
-and not blocked by the panic button
-
-
-==== Free token staking
-
-==== Limited token staking
diff --git a/docs-v1/random-beacon/terms.adoc b/docs-v1/random-beacon/terms.adoc
deleted file mode 100644
index a3fdb4bdaa..0000000000
--- a/docs-v1/random-beacon/terms.adoc
+++ /dev/null
@@ -1,153 +0,0 @@
-:toc: macro
-
-= Terms
-
-ifndef::yellowpaper[toc::[]]
-
-== Conventions
-
-=== Basic conventions
-
-[horizontal]
-Term~context~::
-Globally meaningful terms are capitalized, and usually include subscripts.
-_Term_ specifies the broader type, such as _Stake_, and the subscript _context_
-is used to specify the particular purpose and/or usage of this value.
-+
-Terms are formatted as _CamelCase~snake_case~_.
-
-T~context~::
-Shorthand symbol for commonly used terms. The meaning can be memorized or
-looked up from the shorthand symbol table, as a specific letter always
-corresponds to a specific term.
-
-Term~GLOBAL_CONSTANT~::
-Hardcoded global constants have their subscript in capitals following the
-common programming convention.
-
-C::
-A particularly significant global constant can be expressed as a single capital
-letter. Where this letter corresponds to a shorthand symbol, the constant _C_ is
-of the same type as terms _C~context~_, and could alternatively be expressed as
-_C~IMPORTANT_CONSTANT~_.
-
-Function~context~(input)::
-The value depends on _input_. _Function_ can be (and usually is) a term that is
-normally used as a plain value: eg. _R~submitter~(T)_ means that the submitter
-reward varies depending on time
-
-variable~context~::
-A local value that is only used briefly, or may even be altogether unknown to
-uninvolved participants.
-
-=== Shorthand symbols
-
-Some meanings are used so often that it is useful to have single-letter terms
-for them. Each shorthand symbol maps to a specific longhand term.
-
-TODO: Shorthands and terms have been matched to ensure each term maps to its
-initial wherever possible. The exception is _Penalty_ and _D_ (with
-_disciplinary action_ as a mnemonic); alternatives or abolishing this shorthand
-should be considered.
-
-[horizontal]
-V~i~::
-Value~i~
-+
-The __i__-th output of the random beacon
-
-N~ctx~::
-Number~ctx~
-+
-A number of operators or group members
-
-M~ctx~::
-Malicious~ctx~
-+
-A number of malicious operators or group members
-
-G~ctx~::
-Group~ctx~
-+
-Some specific group
-
-S~ctx~::
-Staker~ctx~
-+
-Some specific staker
-
-P~ctx~::
-Participant~ctx~
-+
-A participant in some group
-
-T~ctx~::
-Time~ctx~
-+
-A block number used as an unambiguous measure of time
-
-R~ctx~::
-Reward~ctx~
-+
-A reward for correct operation; tokens or currency
-
-D~ctx~::
-Penalty~ctx~
-+
-A punishment for misbehavior (mnemonic: _disciplinary_ action); always tokens
-
-=== Common long-form terms
-
-Longhand terms should be self-explanatory wherever possible, and are explained
-locally where they are used. The meanings of some term types that are used
-regularly but don't have a specific shorthand are listed below.
-
-[horizontal]
-Stake~ctx~::
-Some amount of tokens used for staking
-
-Prob~ctx~::
-The probability of some event
-
-== Specific terms
-
-=== Globally significant values
-
-==== Global security parameters
-
-[horizontal]
-N::
-H + M = 2M + 1 = 4M~nofail~ + 1
-+
-Number of participants in a group
-
-H::
-M + 1 = (N - 1)/2 + 1
-+
-Minimum number of honest participants in a group
-
-M::
-H - 1 = (N - 1)/2
-+
-Maximum number of malicious participants in a group beyond which security
-guarantees don't hold
-
-M~nofail~::
-M/2 = (N - 1)/4
-+
-Maximum number of disqualified participants in a group beyond which DKG will
-abort to preserve security
-
-:leveloffset: +1
-
-include::alt_bn128.adoc[]
-
-:leveloffset: +1
-
-include::group-selection/terms.adoc[]
-
-include::dkg/terms.adoc[]
-
-include::signing/terms.adoc[]
-
-include::group-expiration/terms.adoc[]
diff --git a/docs-v1/random-beacon/upgrades.adoc b/docs-v1/random-beacon/upgrades.adoc
deleted file mode 100644
index bb8950186a..0000000000
--- a/docs-v1/random-beacon/upgrades.adoc
+++ /dev/null
@@ -1,81 +0,0 @@
-= Upgrade processes
-
-== Operator contract upgrade
-
-Operator contracts are immutable,
-and are upgraded by deploying a new version in a separate contract.
-The _Registry Keeper_ then approves the new contract on the _registry_,
-and operators are able to authorize it.
-Once authorized by a sufficient number of stakers,
-the contract can be added into the used operator contracts
-of a service contract.
-
-Operator contracts can be upgraded without losing service contract state,
-but critical state is held within the operator contract and cannot be migrated.
-
-. Deploy the new operator contract
-. Approve the operator contract on the registry
-. Wait for stakers to authorize the operator contract
-. Activate the operator contract on the relevant service contract/s
-
-== Service contract upgrade
-
-Because service contracts don't impact the security of staked tokens,
-they can be upgraded in-place without migrating to a new address.
-
-== New service contract
-
-A new service contract is deployed on-chain and listed on the _registry_.
-
-If the service contract doesn't rely on
-an operator contract exclusive to itself,
-it can be deployed after the operator contracts it uses are in place.
-
-Otherwise the service contract must be deployed first,
-inactive because it has no operator contracts it uses.
-Once the address of the service contract is determined,
-the operator contract is deployed,
-approved on the registry,
-and authorized by stakers.
-The operator contract can now be activated on the service contract,
-making it ready to provide services.
-
-. Deploy the new service contract
-. Deploy a new operator contract serving the new service contract
-. Approve the operator contract on the registry
-. Wait for stakers to authorize the operator contract
-. Activate the operator contract on the service contract
-
-== Staking contract upgrades
-
-Staking contracts can be upgraded by deploying a new version,
-and waiting for stakers to migrate
-by withdrawing their stakes on the old contract
-and staking them again on the new contract.
-While stakers are migrating,
-new operator contracts using the new staking contract should be deployed.
-Once stakers have migrated and approved the new operator contracts,
-the contracts can be activated on service contracts.
-
-. Deploy the new staking contract
-. Deploy new operator contracts recognizing the new staking contract
-. Approve the operator contracts on the registry
-. Wait for stakers to migrate to the new staking contract
-. Wait for stakers to authorize the new operator contracts
-. Activate the operator contracts on the service contracts
-
-== Token upgrade
-
-The upgrade process makes it possible to even hard-fork the token
-without disrupting service contract user experience:
-
-. Deploy the new token contract
-. Deploy a migration contract
-that lets holders convert old tokens to new tokens
-. Deploy a new staking contract for the new tokens
-. Deploy new operator contracts recognizing the new token and staking contract
-. Approve the operator contracts on the registry
-. Wait for stakers to convert their tokens,
-stake on the new contract
-and authorize the new operator contracts
-. Activate the operator contracts on the service contracts
diff --git a/docs-v1/relay-states.tex b/docs-v1/relay-states.tex
deleted file mode 100644
index cd904257ce..0000000000
--- a/docs-v1/relay-states.tex
+++ /dev/null
@@ -1,134 +0,0 @@
-\documentclass{article}
-\usepackage[utf8]{inputenc}
-
-\usepackage[margin=1in]{geometry}
-\usepackage{tikz}
-\usepackage[colorlinks=true]{hyperref}
-\usepackage{varwidth}
-
-\usetikzlibrary{positioning}
-\usetikzlibrary{arrows.meta}
-\usetikzlibrary{shapes.symbols}
-\usetikzlibrary{calc}
-
-\tikzset{
- every node/.style={above},
- start state/.style={draw,circle,text width=0},
- state/.style={draw,circle,align=flush center,text width=2cm},
- decision/.style={draw,rectangle,align=flush center},
- thread/.style={draw,signal,signal to=east,fill=white},
- % Nested states and decisions use doubled borders to indicate
- % that you have to reference a different diagram.
- nested state/.style={draw,circle,double,align=flush center},
- nested decision/.style={draw,rectangle,double,align=flush center},
- % Chain states and decisions use dashed borders to indicate
- % that you have to interact with the chain.
- chain state/.style={draw,circle,dashed,align=flush center,text width=2cm},
- chain decision/.style={draw,rectangle,dashed,align=flush center},
- chain transition/.style={draw,dashed},
- % Nested chain decisions combine nested and chain styles to
- % indicate a reference to a different diagram for a state that
- % depends on chain interaction.
- nested chain decision/.style={draw,rectangle,double,dashed,align=flush center},
- % Set default arrow style to stealth.
- >=Stealth
-}
-
-\begin{document}
-
-Below are state diagrams elaborating on the various pieces of a Keep node. Note
-that Keep nodes actually run multiple processes in parallel, for participation
-in the random beacon threshold relay as well as for participating in the Keep
-network. The startup diagram indicates this and links to the subprocess state
-diagrams.
-
-First, however, a legend:
-
-\vspace{0.5cm}
-
-\begin{center}
- \tikz{
- \node[thread] (thread) {A thread};
-
- \node[nested state] (nested state) [below=1cm of thread] {A nested state};
- \node[state] [left=1cm of nested state](state) {A regular state};
- \node[chain state] (chain state) [right=1cm of nested state] {A state dependent on the chain};
-
- \node[nested decision] (nested decision) [below=1cm of nested state] {A nested decision};
- \node[decision] (decision) [left=1cm of nested decision] {A decision};
- \node[chain decision,text width=2cm] (chain decision) [right=1cm of nested decision] {A decision dependent on the chain};
-
- \draw [<-] (-4.5,0.25) -- node [centered,text width=2cm,align=center] {state\\transition} (-2.5,0.25);
- \draw [->,dashed] (2,0.25) -- node [centered,text width=4cm,align=center] {chain-dependent\\state transition} (5.25,0.25)
- }
-\end{center}
-
-\vspace{0.5cm}
-
-Nested states and decisions should link to the nested diagrams that indicate
-what is going on within these states or decisions.
-
-\vspace{0.5cm}
-
-\begin{center}
- \input{img-src/startup-diagram.tikz}
-
- \vspace{0.5cm}
- Keep node startup process: processes run in parallel
-\end{center}
-
-
-
-\clearpage
-
-\begin{figure}
- \centering
- \input{img-src/relay-group-initialization.tikz}
-
- \caption{\label{fig:relay-group-initialization}Relay Group Initialization}
-\end{figure}
-
-\begin{figure}
- \centering
- \input{img-src/relay-group-assignment.tikz}
-
- \caption{\label{fig:relay-group-assignment}Relay Group Assignment}
-
- \vspace{0.5cm}
- % Mildly abusing the itemize env...
- \begin{itemize}
- \item[*] Note that eligibility checking is done by combining the latest relay
- entry with the latest participant registry in a way specified outside
- this document.
- \end{itemize}
-\end{figure}
-
-\begin{figure}
- \centering
- \input{img-src/relay-group-setup.tikz}
-
- \caption{\label{fig:relay-group-setup}Relay Group Setup}
-\end{figure}
-
-\begin{figure}
- \centering
- \input{img-src/relay-entry-request-processing.tikz}
-
- \caption{\label{fig:relay-entry-request-processing}Relay Entry Request Processing}
-\end{figure}
-
-\begin{figure}
- \centering
- \input{img-src/libp2p-join.tikz}
-
- \caption{\label{fig:libp2p-join}{\tt libp2p} Join Process}
-\end{figure}
-
-\begin{figure}
- \centering
- \input{img-src/relay-entry-verification.tikz}
-
- \caption{\label{fig:relay-entry-verification}Relay Entry Verification}
-\end{figure}
-
-\end{document}
diff --git a/docs-v1/rfc/rfc-1-network-security-requirements.adoc b/docs-v1/rfc/rfc-1-network-security-requirements.adoc
deleted file mode 100644
index 4b6bd47930..0000000000
--- a/docs-v1/rfc/rfc-1-network-security-requirements.adoc
+++ /dev/null
@@ -1,217 +0,0 @@
-:toc: macro
-
-= RFC 1: Network Security Requirements
-
-:icons: font
-:numbered:
-toc::[]
-
-
-== Background
-
-Keep is a decentralized network that is anchored to one or more host chains via
-on-chain smart contracts, allowing interactions both on- and off-chain depending
-on the use case. To ensure the safety, security, and integrity of the network,
-the network needs to implement authorization, encryption, and authentication. The
-decentralized nature of the network brings about the unique challenge where
-off-the-shelf protocols (such as TLS) aren't suitable. Specifically, these
-protocols can't be used as-is due to their requirement of trusted central
-authorities and intermediaries. That being said, with some modifications,
-we can make these options more secure and work for our use case.
-
-This document specifies the desired behaviors and properties of a protocol that
-will secure the network layer of Keep.
-
-A successful protocol involves verifying identities (to prevent Sybil attacks),
-ensuring message integrity (to avoid malicious tampering), and allows for the
-encrypting of messages (to ensure that only intended recipients receive a
-message). Furthermore, the protocol should be versioned for easy upgrades.
-
-=== Terminology
-
-peer:: A member of a network that can initiate, accept, and handle secure
- connections.
-network:: A set of peers who are connected to each other, not necessarily p2p.
-chain:: A decentralized, consensus driven store with identities and economic
- incentives.
-stake:: The amount of value a given participant has locked up for participation
- in the network. This value is held on the host chain, and always
- associated with an identity.
-minimum stake:: The minimum amount of value that is required to be a participant
- in the network.
-bootstrap peer:: An authenticated peer that handles requests for joining
- the network from unauthenticated peers. This involves verifying an
- on-chain stake among many other responsibilities.
-
-=== Goal
-
-We aim to authenticate peers, control access to a network where Keep’s protocols
-execute, and provide verifiable private channels between communicating peers.
-
-First and foremost, the protocol should be secure.
-
-==== What is a Secure Protocol?
-
-<> introduces us to the definition of a secure protocol; summarized:
-
-1. If two peers, _P~1~_ and _P~2~_, share a secret key, it is computationally
- infeasible for anyone other than _P~1~_ and _P~2~_ to recover that secret
- key. Both peers can unlock the whole communication, but no other peers can
- understand the communication unless one of the peers chooses to unlock the
- communication.
-
-2. The record of messages shared between _P~1~_ and _P~2~_ to establish the
- authentication of identity must be identical, within a given session,
- regardless of perspective and logically linked (from one message to the
- next).
-
-These constraints prevent replay attacks (re-use of previous messages) and
-interleaving attacks (injecting a message used in previous runs).
-
-==== Capabilities
-
-In addition to being a secure protocol, the protocol must also provide the
-following capabilities:
-
-===== Authentication
-
-The goal of authentication is to provide the communicating parties with some
-assurance that they know each others' identities.
-
-An authenticated peer is a known identity in the network such that all messages
-from the authenticated peer, _P~i~_, can be provably linked to _P~i~_.
-
-Given an authenticated peer and an unauthenticated peer, the unauthenticated peer
-must provide the authenticated peer proof of ownership of an on-chain identity
-with an associated stake. If an authenticated peer's stake falls below the
-minimum stake for any reason, then an authenticated peer becomes unauthenticated.
-
-===== Authorization
-
-The goal of authorization is to ensure that capabilities within the system are
-restricted to authenticated identities.
-
-The only capabilities unauthenticated peers have are sending an initialization
-message to bootstrap peers.
-
-Bootstrap peers are authenticated peers that accept connections from
-unauthenticated peers and attempt to authenticate those peers.
-
-Authenticated peers can send and accept all kinds of messages.
-
-Further access and capabilities are restricted by the individual protocols.
-
-
-==== Required Properties
-
-A secure protocol that is capable of authenticating and authorizing peers should
-also guarantee **integrity**, **attributability**, and (optionally)
-**confidentiality**.
-
-A protocol that enforces **integrity** is one in which data sent over the network
-by authenticated peers cannot be modified by adversaries without detection.
-
-**Attributability** enforces that a message from a given peer is known to be from
-that peer.
-
-Furthermore, successful attributability requires replay protection (which implies
-message ordering enforcement). Consider the following case: an insecure scheme
-would allow an adversary to intercept the communications between two peers,
-modify the contents of a message (particularly of a message that has already been
-received and processed by the receiving peer), and continue forwarding the
-communication off to the receiving end. A receiver with an improper
-implementation would process this message like any other, believing it was from
-the intended sender. This would allow the adversary to forge communications with
-a unsuspecting recipient as if they were the sender!
-
-Our protocol optionally provides **confidentiality**, where a message sent
-from an authenticated peer is only intelligible to the communicating,
-authenticated peers.
-
-
-=== Scenarios
-
-The protocol should be able to satisfy some known scenarios, described below,
-though this should not be considered a comprehensive list.
-
-==== Joining the network
-
-An unauthenticated peer wants to become an authenticated peer in the Keep
-Network. This peer must be, first and foremost, successfully staked (otherwise
-dishonest participants can't be punished). Furthermore, the peer must prove their
-stake to the members of the network.
-
-The _authentication_ and _authorization_ capabilities cover the requirements of
-this example. Specifically, _authentication_ allows a peer to validate the
-identity of the unknown peer. _Authorization_ enables the following:
-
-1. The restriction of the unknown, untrusted peer to only send the initial
- request to be authenticated.
-2. The capability of an authenticated peer to respond to on-chain events or to
- network-specific events.
-3. The disconnection from the network for members who fall below the minimum
- stake.
-
-==== Point-to-Point communications
-
-A peer wishes to send a point-to-point message such that only the intended
-recipient can inspect and verify the contents of the message.
-
-This example presumes that the identity is verified and accepted in the network,
-which means that _authentication_ and _authorization_ are satisfied.
-_Confidentiality_ is needed to ensure that the communicating peers can
-communicate in secret. _Integrity_ ensures that the message hasn't been tampered
-with in transit over the wire. _Attributability_ ensures that if either peer
-sends a message which contains a payload that would result in punishment, the
-correct peer will be punished.
-
-
-== Summary
-
-Given the above, we are primarily concerned with authentication and key exchange.
-The literature overwhelmingly recommends a solution which provides authentication
-and key-exchange considered jointly. Per <>:
-
-> A protocol providing authentication without key exchange is susceptible to an
-> enemy who waits until the authentication is complete and then takes over one
-> end of the communications line. Such an attack is not precluded by a key
-> exchange that is independent of authentication. Key exchange should be linked
-> to authentication so that a party has assurances that an exchanged key (which
-> might be used to facilitate privacy or integrity and thus keep authenticity
-> alive) is in fact shared with the authenticated party, and not an impostor. For
-> these reasons, it is essential to keep key exchange in mind in the design and
-> analysis of authentication protocols.
-
-Our system has two levels of key exchange:
-
-1. An out-of-band process for confirming an on-chain identity (is the peer
- attempting to join the network staked).
-2. Ephemeral key exchange for the purposes of authenticating in-network
- identities and sending confidential messages (is the peer sending this
- message really who they say they are).
-
-== Open Questions
-
-* Is a requirement for communicating participants that they be online?
-
-* Should all communications between Keep nodes be encrypted in order to provide
-confidentiality for all transcripts between nodes?
-
-[bibliography]
-== Related Links
-
-* [[[AAKE]]] Diffie W. (1992)
- Authentication and Authenticated Key Exchanges
- In: Designs, Codes and Cryptography, 2, 107-125 (1992), Kluwer Academic Publishers
- http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.216.6107&rep=rep1&type=pdf
-
-* Discussions on writing this document:
-** https://www.flowdock.com/app/cardforcoin/tech/messages/152290
-** https://www.flowdock.com/app/cardforcoin/tech/messages/153124
-** https://www.flowdock.com/app/cardforcoin/tech/messages/153592
-
-* t-ECDSA performance with some thoughts on network performance optimizations:
- https://www.flowdock.com/app/cardforcoin/tech/messages/154946
-
-* Desired properties of confidentiality in Keep's network:
- https://www.flowdock.com/app/cardforcoin/tech/messages/156769
diff --git a/docs-v1/rfc/rfc-11-upgrade-authorizations.adoc b/docs-v1/rfc/rfc-11-upgrade-authorizations.adoc
deleted file mode 100644
index a3ccb46508..0000000000
--- a/docs-v1/rfc/rfc-11-upgrade-authorizations.adoc
+++ /dev/null
@@ -1,461 +0,0 @@
-:toc: macro
-
-= RFC 11: Authorizations in the upgrade scheme
-
-:icons: font
-:numbered:
-toc::[]
-
-== Background
-
-Securely upgradeable work contracts
-are important for protecting stakers' tokens.
-The current design for dividing work contracts
-into operator contract and service contract components
-permits secure upgrades of operator contracts
-without interfering with service functionality.
-To gain the theoretical benefits from this scheme,
-it is necessary to specify how contract upgrades should be authorized,
-and by whom.
-
-=== Current Functionality
-
-In link:rfc-9-upgradeable-contract-components.adoc[RFC 9: Upgrading contracts by separate components],
-the division between operator and service contracts is established.
-Apart from the existing consensus
-that stakers should authorize each operator contract individually,
-there is no overarching design for secure contract upgrades yet.
-
-== Proposal
-
-To achieve secure upgrades, this RFC proposes a scheme
-where the upgrade process is centered on operator contracts,
-which tie all components of the network together.
-
-Operator contracts are subject to approval
-globally on a _registry_,
-in their respective _service contracts_,
-and individually from each staker in the _staking contract_.
-This provides multilayered protection
-against a variety of different risks.
-
-Other contracts such as service contracts and staking contracts
-are hard-coded in operator contracts,
-so attackers are prevented from inserting arbitrary contracts of any type
-without needing to have separate approval processes
-for different contract types.
-
-Different keys are used in different parts of the upgrade process.
-The roles of global _Registry Keeper_ and _Panic Button_,
-service contract-specific _Operator Contract Upgraders_,
-and staker-specific _Authorizers_,
-are used to divide the responsibilities
-and to provide resiliency against compromise of individual keys.
-A _Governance_ scheme can be used to rekey the roles
-to recover from non-catastrophic compromise.
-
-The multilayered approach permits upgrading staking contracts,
-or even the token itself,
-without disrupting user experience on the service contract.
-
-=== Goal
-
-The main goals are to provide a smooth upgrade path for future functionality,
-limiting the impact of single-key compromise,
-and protecting stakers' funds from ever being subject
-to code they haven't individually authorized.
-
-=== Roles
-
-==== Governance
-
-Governance is the final arbiter of authority in the Keep Network.
-While exact details of the implementation of Governance
-are out of scope for this RFC,
-the role of Governance in the upgrade process
-is to enable recovery from key compromise by rekeying other roles.
-
-Governance has the authority to change the addresses of
-the _Registry Keeper_, _Panic Button_,
-and the service contracts' _Operator Contract Upgraders_.
-
-The rekeying process should prioritize security over convenience
-to the greatest feasible extent,
-being unsuitable for ordinary upgrades
-but permitting recovery from partial system compromise
-under extraordinary circumstances.
-
-==== Registry Keeper
-
-The Registry Keeper maintains the global _registry_
-of approved operator contracts.
-Each operator contract must be approved by the Registry Keeper
-before it can be authorized by a staker
-or used by a service contract.
-
-The Registry Keeper can be rekeyed by _Governance_.
-
-==== Panic Button
-
-The Panic Button can disable malicious or malfunctioning contracts
-that have been previously approved by the Registry Keeper.
-When a contract is disabled by the Panic Button,
-its status on the _registry_ changes to reflect this,
-and it becomes ineligible to penalize stakers.
-Contracts disabled by the Panic Button can not be reactivated.
-
-The Panic Button can be rekeyed by _Governance_.
-
-==== Operator Contract Upgrader
-
-Each service contract has a Operator Contract Upgrader
-whose purpose is to manage operator contracts for that specific service contract.
-The Operator Contract Upgrader can add new operator contracts
-to the service contract's operator contract list,
-and deprecate old ones.
-
-The Operator Contract Upgraders can be rekeyed by _Governance_.
-
-==== Authorizer
-
-Each staker has an Authorizer
-whose purpose is to authorize operator contracts the staker wishes to operate on.
-Authorized operator contracts are permitted to impact the staker's staked tokens
-via punishments or rewards.
-
-The Authorizer cannot be rekeyed except by undelegating and redelegating.
-
-=== Types of contracts
-
-==== Registry
-
-A global registry is used to keep track of all operator contracts,
-ensuring that only Keep Org-approved operator contracts are used,
-and enabling the panic button to disable operator contracts in an emergency.
-
-The registry contains all operator contracts of the Keep network.
-Each contract's status may be `NULL`, `APPROVED` or `DISABLED`.
-
-A status of `NULL` is the default
-and means that the operator contract has not been approved by the _Registry Keeper_.
-
-When the _Registry Keeper_ approves a operator contract,
-its status switches to `APPROVED` in the registry.
-Approved operator contracts can be authorized by stakers to impact their stakes,
-and service contracts may utilize them.
-
-The _Panic Button_ can be used
-to set the status of an `APPROVED` contract to `DISABLED`.
-Operator Contracts disabled with the _Panic Button_ cannot be re-enabled.
-
-==== Operator Contracts
-
-Operator contracts serve other contracts,
-and are responsible for all operations involving staked tokens.
-
-The requirement for stakers' funds to never be subject to
-code they haven't approved individually
-has certain implications on operator contracts:
-the contracts must be immutable;
-and any external sources of truth,
-e.g. token contract and staking contract/s,
-must be hard-coded.
-
-In the current design,
-operator contracts authorized to punish the staker
-can never be deauthorized.
-Even if authorization was revokable,
-the stakers should not be expected to react promptly
-to malicious changes to operator contracts.
-
-An operator contract can either provide services
-to any contract that makes a valid request and pays the correct fee,
-or it can be owned is owned by a specific contract and only serve its owner.
-
-Recognized staking contracts::
-Each operator contract specifies one or more _staking contracts_ it recognizes.
-Every operator contract that handles stakes
-must recognize at least one staking contract.
-Recognized staking contracts are hard-coded and unchangeable.
-
-==== Service Contracts
-
-Service contracts provide services without directly interacting with operators,
-but using a set of operator contracts in some way.
-Service Contracts don't need to be aware of tokens or staking in any way;
-these functions are entirely intermediated by the operator contracts.
-A service contract only needs a list of which operator contracts it uses.
-To permit system upgrades,
-the list of used operator contracts can be updated with proper authorization.
-
-Used operator contracts::
-A mutable list of operator contracts used by the service contract.
-
-Each service contract has a list
-of zero or more operator contracts it may use.
-
-A service contract is deployed with zero operator contracts,
-rendering the service contract inactive
-until at least one operator contract is activated.
-
-Each service contract has a _Operator Contract Upgrader_
-who can add used operator contracts.
-To add a used operator contract,
-the operator contract must have been `APPROVED` on the _registry_.
-
-If a operator contract has been `DISABLED` by the _Panic Button_,
-it is ineligible for work selection.
-This must be checked when the service contract selects an operator contract.
-
-==== Staking contracts
-
-Staking contracts hold staked tokens and enforce staking rules.
-They must permit authorized operator contracts
-to slash the stakes of misbehaving operators,
-but stakers must be protected from code they haven't authorized individually.
-
-For this purpose, each staking contract maintains a list
-of operator contracts that have been authorized by each staker's _Authorizer_.
-The list of operator contracts could also be maintained globally,
-removing the need for entry duplication
-when stakers on different staking contracts
-have the same Authorizer and operate on the same operator contract.
-However, maintaining the authorizations locally
-may be cheaper than cross-contract calls,
-and the scenario where gas would be saved is likely to be rare.
-
-(If _fully backed operation_ is used,
-it may not be necessary to have separate authorizations
-as stakes are explicitly allocated for each operator contract.)
-
-Staking contracts are also aware of the token contract by necessity.
-
-===== Authorized operator contracts
-
-The _authorized operator contracts_ are a mapping
-of `(address authorizer, address operator_contract) -> status`.
-
-The status of a contract may be either `NULL` or `AUTHORIZED`.
-A status of `NULL` is the default
-and means the operator contract is not authorized.
-A status of `AUTHORIZED` means that the operator contract
-may affect the stakes of those stakers
-who have assigned that `authorizer` as their _Authorizer_.
-
-To authorize a operator contract on a staking contract,
-the following conditions must apply:
-
-- the operator contract has been `APPROVED` on the _registry_
-- the operator contract recognizes the staking contract
-
-Once a operator contract has been authorized,
-authorization cannot be withdrawn by the staker.
-However, a operator contract that has been `DISABLED` by the _Panic Button_
-may not punish stakers.
-
-=== Upgrade processes
-
-==== Operator Contract upgrade
-
-. Deploy the new operator contract
-. Approve the operator contract on the registry
-. Wait for stakers to authorize the operator contract
-. Activate the operator contract on the relevant service contract/s
-
-==== New service contract
-
-. Deploy the new service contract
-. Deploy a new operator contract serving the new service contract
- . Approve the operator contract on the registry
- . Wait for stakers to authorize the operator contract
- . Activate the operator contract on the service contract
-
-==== Staking contract upgrade
-
-. Deploy the new staking contract
-. Deploy new operator contracts recognizing the new staking contract
- . Approve the operator contracts on the registry
- . Wait for stakers to migrate to the new staking contract
- . Wait for stakers to authorize the new operator contracts
-. Activate the operator contracts on the service contracts
-
-==== Token upgrade
-
-The upgrade process makes it possible to even hard-fork the token
-without disrupting service contract user experience:
-
-. Deploy the new token contract
-. Deploy a migration contract
-that lets holders convert old tokens to new tokens
-. Deploy a new staking contract for the new tokens
- . Deploy new operator contracts recognizing the new token and staking contract
- . Approve the operator contracts on the registry
-. Wait for stakers to convert their tokens,
-stake on the new contract
-and authorize the new operator contracts
-. Activate the operator contracts on the service contracts
-
-=== Impact of compromise
-
-==== Individual keys
-
-===== Registry Keeper
-
-A compromised Registry Keeper can approve arbitrary operator contracts.
-Because using those operator contracts for a service contract
-requires the service contract's Operator Contract Upgrader as well,
-the impact is limited to stakers being able to instantly unstake
-by authorizing a malicious operator contract
-which slashes their stakes
-and sends the tokens to an address controlled by the staker.
-
-===== Panic Button
-
-A compromised Panic Button can disable all operator contracts
-and halt all network services.
-Recovery is impossible until Governance has rekeyed the Panic Button.
-
-This is inevitable due to the functionality of the Panic Button,
-but the impact could be mitigated
-by setting a cap on how many times the Panic Button can be invoked
-within a particular timeframe.
-However, such a cap would be overwhelmed
-by a mass approval of malicious contracts by the other roles.
-
-===== Operator Contract Upgrader
-
-A compromised Operator Contract Upgrader
-can activate arbitrary operator contracts
-within the strict constraints of the upgrade process.
-Without compromise of the Registry Keeper
-to approve new malicious operator contracts,
-it is unlikely that a compromised Operator Contract Upgrader alone
-would have significant impact on the network.
-
-===== Authorizer
-
-If only the Authorizer of some staker is compromised,
-the attacker can authorize operator contracts
-that have been approved by the Registry Keeper,
-and that recognize the contract that staker stakes on.
-
-This has a very limited negative impact
-unless the Registry Keeper has approved
-a faulty or malicious operator contract.
-
-==== Key combinations
-
-===== Registry Keeper + Operator Contract Upgrader
-
-If a malicious operator contract can get globally approved,
-the impacted service contract can be completely subverted
-by deprecating all other operator contracts
-and returning malicious values.
-While already existing operations should finish normally,
-the service contract can be rendered effectively useless for new requests.
-
-===== Registry Keeper + Authorizer
-
-Approving and authorizing a malicious operator contract
-permits theft of staked funds.
-
-=== Limitations
-
-Each operator contract upgrade requires participation
-from both the _Registry Keeper_ and the _Operator Contract Upgrader_.
-This increases the exposure of these keys,
-leading to a higher risk of simultaneous compromise.
-
-== Future Work
-
-Service contracts could have upgradeable components
-for performing various sub-tasks.
-These components could be upgraded
-with a process similar to that of operator contracts
-except without staker involvement.
-
-=== Keeps, factories and vendors
-
-==== Operator contracts
-
-===== Keep factories
-
-Keep factories are operator contracts
-that create keeps for customer applications.
-
-Like all operator contracts,
-each Keep factory recognizes one or more staking contracts
-for the purpose of determining operators' eligibility to join keeps.
-
-Each keep factory implements one or more keep interfaces.
-The factory records its interfaces
-and the addresses of the corresponding keep vendors.
-
-===== Keeps
-
-Keeps are operator contracts created by keep factories.
-When a contract requests a keep from a factory,
-the factory creates a new contract owned by the customer contract, the keep,
-and hands it off to the customer contract.
-
-Keeps aren't individually authorized to slash stakers.
-Instead, they have to use the authorization of their creator factory.
-
-Once created, a keep cannot be upgraded in any way,
-except by closing the keep and opening another one.
-
-==== Service contracts
-
-===== Keep vendors
-
-Keep vendors are service contracts
-which perform version management of keep factories.
-Keep vendors provide customers
-a single unified interface to request up-to-date keeps.
-
-The upgrade process of the Keep Network
-is designed to eliminate the security threat
-posed by unilateral smart contract upgrades.
-However, the consent-centered upgrade process
-is inherently more complex to accommodate
-than a simple switchover to a new version.
-Stakers will authorize a new contract
-and operators will upgrade their client software
-on their own schedule,
-so the initial capacity of a new keep version will be seriously limited.
-
-Instead of updating the factory address when a type of keep is upgraded,
-and explicitly accommodating for the friction in the migration,
-a customer application can go through the vendor of the corresponding keep type
-to receive a recent version of the keep.
-For most applications,
-the convenience of having the version migration
-managed automatically by the keep vendor
-is likely to be more significant than the slight security impact.
-
-== Open Questions
-
-Some threats may be mitigated by allowing or requiring
-routine rekeying of the upgrade roles
-using the upgrade roles' own keys instead of relying on governance.
-This has not been investigated yet.
-Alternatively, each role could have a backup key in cold storage,
-usable as the first-line rekeying option.
-
-The governance process for recovery from key compromise is left open.
-Involving a significant fraction of stakers (e.g. 33-50%)
-has the attractive property that
-an adversary capable of subverting the governance process
-would necessarily be powerful enough
-to subvert the honest majority assumption in individual Keeps.
-This means that rekeying is robust against attacks
-unless the network as a whole is compromised.
-
-It is not immediately clear whether service contracts should
-completely block operator contracts disabled with the panic button,
-or only deprecate them without regard for the normal limitations.
-
-Rate-limiting the Panic Button can help prevent total DoS
-if the panic button is ever compromised,
-but also permits flooding the system with malicious operator contracts
-unless the Registry Keeper is similarly rate-limited.
diff --git a/docs-v1/rfc/rfc-12-keep-network-interface.adoc b/docs-v1/rfc/rfc-12-keep-network-interface.adoc
deleted file mode 100644
index adf0ed035a..0000000000
--- a/docs-v1/rfc/rfc-12-keep-network-interface.adoc
+++ /dev/null
@@ -1,194 +0,0 @@
-:toc: macro
-
-= RFC 12: Keep Network application interface
-
-:icons: font
-:numbered:
-toc::[]
-
-
-== Proposal
-
-This document specifies how applications interact with Keep Network.
-
-=== Terminology
-
-Application:: Application is an external smart contract or a set of smart
- contracts utilizing functionalities offered by Keep Network.
-
-a keep:: A keep is a smart contract used by an application to perform some work.
- It is a privacy primitive enabling secure storage and usage of secrets.
-
-sMPC cluster:: A keep can have off-chain clients executing work for a keep.
- Off-chain clients serving a keep together form an sMPC cluster.
- An sMPC cluster observes state of a keep and reacts appropriately.
-
-Keep Network:: The Keep network consists of all stakers, all keeps and
- associated sMPC clusters, and the random beacon.
-
-KEEP:: KEEP is an ERC-20 work token used to stake in the Keep network.
- A minimum staked value is required for operator to join sMPC cluster.
-
-Keep Core:: Keep Core consist of a set of on-chain contracts and off-chain
- sMPC cluster providing the functionality of random beacon
- and KEEP token along with all stake management interfaces.
-
-tECDSA:: Threshold Elliptic Curve Digital Signature Algorithm.
-
-Bond:: A bond is collateral provided by a keep operator that disincentivizes
- collusion and misbehavior. Bond may get slashed or seized in case of
- malicious behaviour of the operator.
-
-=== Goal
-The goal of this proposal is to specify the interface between an application and
-the keeps atop which the application is built. This proposal specifies the
-mechanism of creating and registering keeps. This proposal introduces two types
-of keeps: tECDSA keep and Bonded tECDSA keep. Those keeps are just the first
-two types of keeps which are going to be offered by Keep Network.
-All components described in this proposal meet the requirements described in
-the <> addressing
-upgradeability mechanics.
-
-==== sMPC cluster requirements
-
-Each off-chain client of sMPC cluster should be a separate process. Keep Core
-client should be a separate client than Keep tECDSA client:
-```
-./keep-core
-./keep-tecdsa
-```
-
-(The above snippet is just an example for the first keep type)
-
-Each staker is required to run Keep Core client. Running Keep tECDSA client is
-optional. Eventually, we hope other developers will build their own clients.
-
-==== Bonding requirement
-
-Some applications requires a bond to be provided by stakers. Stakers who want to
-participate in the given protocol need to opt-in and provide the required bond.
-A bond can be provided in ETH or ERC-20 token specific to the application.
-
-=== Types of keeps
-
-There are two first types of keeps that are going to be offered by Keep Network:
-tECDSA keep and bonded tECDSA keep.
-
-tECDSA keep:: tECDSA keep is a type of a keep allowing to sign data with
- a uniquely generated private key for each new keep instance. Key
- generation and signing are based on trustless, threshold protocols
- executed by groups of signers forming an sMPC cluster for this
- type of a keep.
-
-bonded tECDSA keep:: bonded tECDSA keep is a tECDSA keep with an extra bonding
- logic over a vanilla tECDSA keep. Each staker being a part
- of sMPC cluster for this type of keep needs to provide an
- extra bond required for each new instance of bonded tECDSA
- keep. The bond can be slashed as a result of inactivity or
- misbehaviour during tECDSA key generation or signing.
-
-=== Implementation
-
-==== Keep factory
-
-Keep factory is a smart contract used to create instances of a keep of a certain
-type. Each type of keep has a separate keep factory. Each keep factory is an
-operator contract and has to be sanctioned by stakers as such. Application
-developers may interact with factory directly if they decide to. The network
-can not guarantee that old factories will be still backed up by enough stakers,
-though.
-
-==== Vendor
-
-A vendor is a smart contract with which the application interacts to obtain the
-new instance of a keep of the given type backed by enough stakers so that all
-operations on the created keep can go smoothly. Vendor interacts with keep
-factories choosing the one most recent if it is backed by enough stakers. Each
-vendor is a service contract and does not have to be sanctioned by stakers. Each
-vendor can operate on several versions of keep factory to allow for a smooth
-upgrade process.
-
-==== Keep registry
-
-The keep registry serves the role of the master list (see RFC 11 for more details)
-and tracks sanctioned staking contracts, operator contracts (including keep
-factories) and vendors. It ensures that only approved contracts are used.
-A new type of keep can be added without upgradeable registry.
-
-=== Pseudocode
-
-==== ECDSA keep vendor
-```
-contract ECDSAKeepVendor {
- address[] internal _factories;
-
- function openKeep(
- uint256 threshold,
- uint256 groupSize,
- address owner
- ) returns (address) {
- address factory = selectFactory()
- return ECDSAKeepFactory(factory).openKeep(
- threshold, groupSize, owner
- )
- }
-}
-```
-
-==== ECDSA keep factory
-```
-contract ECDSAKeepFactory {
- function openKeep(
- uint256 threshold,
- uint256 groupSize,
- address owner
- ) returns (address) {
- address keep = new ECDSAKeep(
- selectGroup(threshold, groupSize),
- owner
- );
-
- return keep;
- }
-}
-```
-
-==== ECDSA keep
-```
-contract ECDSAKeep {
-
- function sign() {
- require(msg.sender == _owner, "Only keep owner can ask to sign");
- // (...)
- }
-}
-```
-
-==== Keep registry
-```
-contract KeepRegistry {
-
- function getKeepVendor(string keepType) address {
- // (...)
- }
-}
-```
-
-==== Application
-```
-contract Application {
- address internal _keepRegistry;
-
- function openDeposit() {
- address vendor = KeepRegistry(_keepRegistry).getKeepVendor("ECDSA")
- vendor.openKeep(
- threshold,
- groupSize,
- bond
- );
-
- // (...)
- }
-}
-```
-
diff --git a/docs-v1/rfc/rfc-13-continuous-delivery.adoc b/docs-v1/rfc/rfc-13-continuous-delivery.adoc
deleted file mode 100644
index 551a037d2c..0000000000
--- a/docs-v1/rfc/rfc-13-continuous-delivery.adoc
+++ /dev/null
@@ -1,299 +0,0 @@
-:toc: macro
-
-= RFC 13: Continuous Delivery
-
-:icons: font
-:numbered:
-toc::[]
-
-[abstract]
-.Abstract
-
-Here we present a continuous delivery method for a service or services running
-in a Kubernetes cluster. It is expected that one or more of these services
-has Ethereum contracts developed alongside the service. It is expected that
-there is a relationship between service and contract to a degree that we must
-ensure both service and contract are deployed continuously. The entirety of the
-solution is targeted at development and test environments. The requirements for
-utilizing the outlined approach in production will not be covered here. Our one
-and only service at this time is the keep-client. The RFC will focus on the
-keep-client as a result, however the solution is applicable outside the
-keep-client. This RFC requires a basic understanding of Kubernetes objects.
-
-
-== Background
-
-There are *three* parts to deployments with keep-clients:
-
-*Service Code and Service Configuration:*
-
-Deploying manually is a pain in the ass, even at a few client deployments (5) the
-manual process is untenable. It's possible to manage this manually at such a low
-number of clients though you run a non-trivial risk of human error and deployment
-step repetition as as result. This has an adverse effect on both the engineering
-experience and time efficiency.
-
-When scaling the solution beyond 5 clients manual configuration becomes untenable
-regardless of due-diligence.
-
-*Contract Code:*
-
-The keep-client service leans on a collection of Ethereum contracts that are in
-development alongside the service. When contracts are changed they have to be
-deployed to the Ethereum network that the keep-clients are connecting to.
-
-This arrangement creates a dependency between the service configuration and
-contract code on a couple levels:
-
-1. keep-client configuration files require contract addresses. These addresses
-change when contracts are updated. This means we need to be aware of contract
-changes on the keep-client configuration side and make sure keep-client
-configuration files get updated contract addresses.
-
-2. We can assume keep-client code will be updated to utilize the latest contract
-functionality. We can assume that this may or may not break keep-client
-behavior if the service is deployed against old contracts. This can potentially
-happen the other way around as well, where an updated contract is deployed and
-removes/changes functionality an old keep-client can't deal with. Therefore
-we must ensure both keep-clients and Keep contracts get deployed together,
-contracts before clients due to client startup behavior.
-
-=== Sample keep-client Service Configuration File
-
-*Bootstrap Peer*
-```
-# This is a TOML configuration file for DKG, P2P networking and connection to Ethereum
-
-# Provider Initialization Example
-
-[ethereum]
- URL = "ws://eth-host:ws-port"
- URLRPC = "http://eth-host:rpc-port"
-
-[ethereum.account]
- Address = "0x6299496199d99941193fdd2d717ef585f431ea05"
- KeyFile = "path/to/in-use/keyfile"
-
-[ethereum.ContractAddresses]
- # Hex-encoded address of KeepRandomBeaconOperator contract
- KeepRandomBeaconOperator = "0x6299496449d11141193fdd2d717ef585f431er02"
- # TokenStaking
- Staking = "0x6297776199d99942293fdd2d717ef585f431er03"
-
-# Bootstrap node creating a new network.
- [LibP2P]
- Seed = seed-number-for-id-generation
- Port = keep-client-port
-
-```
-
-*Standard Peer*
-```
-# This is a TOML configuration file for DKG, P2P networking and connection to Ethereum
-
-# Provider Initialization Example
-
-[ethereum]
- URL = "ws://eth-host:ws-port"
- URLRPC = "http://eth-host:rpc-port"
-
-[ethereum.account]
- Address = "0x6299496199d99941193fdd2d717ef585f431ea05"
- KeyFile = "path/to/in-use/keyfile"
-
-[ethereum.ContractAddresses]
- # Hex-encoded address of KeepRandomBeaconOperator contract
- KeepRandomBeaconOperator = "0x6299496449d11141193fdd2d717ef585f431er02"
- # Hex-encoded address of TokenStaking contract
- Staking = "0x6297776199d99942293fdd2d717ef585f431er03"
-
-[LibP2P]
- Peers = ["comma separated list of bootstrap peers"]
- Port = keep-client-port
-
-```
-
-
-=== Current Functionality
-
-We currently have a single cloud environment (`keep-dev`) that is in a mixed state of
-continuous delivery and manual configuration. Current functionality will be
-outlined as the "three parts" described in Background.
-
-*keep-client Service Deployment:*
-
-keep-client service deployment is done automatically whenever code is merged to
-master. This is facilitated by a lightweight tool called https://keel.sh/[Keel] that runs
-in the Kubernetes cluster. This is a pull based deployment mechanism where Keel
-is subscribed to our container registry and listens for publish events. On image
-publish Keel checks Kubernetes deployments for annotations and matches labels set
-there for what should be deployed. On match Keel pulls the image and does a
-deployment.
-
-- Keel Infrastructure: https://github.com/thesis/infrastructure/tree/master/terraform/modules/gcp_pull_deploy[Keel Terraform Module]
-`keep-dev`
-- Keel Implementation: https://github.com/keep-network/keep-core/blob/master/infrastructure/terraform/keep-dev/main.tf#L186-L201[keep-dev Terraform main.tf]
-
-
-*keep-client Configuration:*
-
-Our first goal was to separate service configuration from the service image.
-This exists in the form of each deployed keep-client having its own Kubernetes
-ConfigMap. This allows for the use of a "standard" keep-client service image
-across all deployed keep-clients. There are two pieces of data that make up a
-keep-client ConfigMap:
-
-1. keep-client-config.toml
-2. Ethereum keyfile
-
-Configuration of the data that populates the ConfigMaps and ConfigMaps themselves
-are updated *manually*.
-
-- Maintenance log and Kubernetes CRUD commands: https://github.com/keep-network/keep-core/blob/master/infrastructure/kube/keep-dev/kube-setup.org[kube-setup]
-- keep-client config files: https://github.com/keep-network/keep-core/tree/master/infrastructure/kube/keep-dev/keep-client/config[keep-client.toml]
-
-*Ethereum Contract Deployment:*
-
-Ethereum contracts and subsequent steps are managed against `keep-dev` *manually*.
-This is done from a local machine on the `keep-dev` VPN using Truffle.
-
-It's worth noting that when contracts are deployed we need to do the following:
-
-1. Ensure Ethereum accounts are unlocked.
-2. Stake Ethereum accounts with KEEP tokens.
-3. Update the keep-client configuration files and ConfigMaps with new contract
- address. (see previous section)
-4. re-deploy keep-clients.
-
-Sample Commands:
-
-```shell
-# migrate contracts
-truffle migrate --reset --network keep_dev
-
-# unlock ETH accounts
-KEEP_ACCOUNT_PASSWORD=eth-account-passphrase \
- truffle exec ./unlock-eth-accounts.js --network keep_dev
-
-# stake ETH accounts
-truffle exec ./delegate-tokens.js --network keep_dev
-```
-
-
-== Proposal
-
-To bring parts `Ethereum Contract Deployment` and `keep-client Configuration`
-into automated configuration such that they can be continuously deployed with
-the already automated `keep-client service` deployment.
-
-=== Goal
-
-To automatically provision the `keep-dev` environment on master merge with all
-appropriate configurations and app code without human intervention.
-
-=== Implementation
-
-To reiterate: The implementation will aim to automate
-`Ethereum Contract Deployment` and `keep-client Configuration`.
-`keep-client service deployment` is already automated via Keel.
-
-==== Part 1: Contract Migration
-
-Either a new workflow or new jobs to existing workflow will be added to the
-`keep-core` circle config. Before image publish on master merge Circle
-will run this workflow/job to trigger a script that will:
-
-- migrate all contracts
-
-- Copy compiled contract JSON to Circle and store in a Workspace for persistence
- in the `InitContainer` image.
-
-- Here we must implement an access point for Circle into the private Kubernetes
- cluster. We can do this with the `gcp_push_deploy` Terraform module.
-
-==== Part 2: keep-client Preparation
-
-On each keep-client Kubernetes deployment we'll run an `InitContainer` that does
-the following:
-
-- create ETH account
-- unlock ETH account
-- stake ETH account
-- write contract addresses, ETH host/port, bootstrap peer addresses to config
- template
-- write configuration file and ETH account keyfile to a persistent volume
-- mount configuration file / keyfile persistent volume to keep-client deployment
-
-The `InitContainer` will operate exclusively on the ETH account and assigned to the
-`keep-client` being deployed. If there are 100 `keep-client` Kubernetes
-deployments, there would be 100 `InitContainer` instances unlocking and staking
-for each of the assigned ETH accounts. This is infinitely scalable (system
-resources aside) and reduces `unlock + stake` time to a ceiling of the time it
-takes to operate on a single account.
-
-The `InitContainer` will have a copy of each Keep contracts compiled JSON. The
-files will be used to fetch contract ABI's for account staking and contract
-addresses for configuration file setup. The updated configuration values will be
-fed into a complete `keep-client` configuration template and stored in a Kubernetes
-persistent volume. This volume will be mounted to the `keep-client` deployment
-where the config can be passed via command line argument on service start.
-
-For now we're going to bake a custom image for the `InitContainer` with the script
-for doing ETH account creation, unlock and stake, and keep-client configuration.
-This will be checked into the `keep-core/infrastructure/kube` directory.
-
-==== A Note On Configuration Value Scope
-
-We provide configuration values via environment variables at two points in this
-process: Circle contexts and Kube deployment configuration files.
-
-We have *environment* and *client* properties. Where some N configuration values
-are of context/properties environment and some are of context/properties client.
-Environment properties
-
-An example:
-
-Using the *environment*/*client* context to organize configurations we can draw a
-line at where config values get populated.
-
-`ETH_HOSTNAME` is a property of the environment, where `KEEP_CLIENT_ETH_ACCOUNT`
-is a property of a client (because we’ve assigned it so).
-
-Environment context property `ETH_HOSTNAME` gets configured at the Circle context
-level and baked into the `InitCointainer` and `KEEP_CLIENT_ETH_ACCOUNT`
-gets configured on the Kube deployment.
-
-
-=== Limitations
-
-- It requires Kubernetes
-- It requires Keel
-- It require CircleCI
-- It requires Truffle
-- All contracts are migrated, can't be selective
-- No rollback mechanism if things go sideways
-- No order to which type of keep-client gets deployed first (bootstrap vs standard)
-
-=== Proof of Concept
-
-`keep-dev` is running Keel. Code is already referenced.
-
-
-== Future Work
-
-Open
-
-== Open Questions
-
-Open
-
-[bibliography]
-== Related Links
-
-- https://www.flowdock.com/app/cardforcoin/tech/threads/oa1X0y9kQqUBwxd4gwgdu7Rs5O2[Consul discussion]
-- https://www.flowdock.com/app/cardforcoin/keep/threads/zzxutnh8USazp5U8cC6lNIDu7gI[Contract Migration discussion]
-- https://www.flowdock.com/app/cardforcoin/tech/threads/LFkufyZX1RBawClTZp6kO0raeq0[Testing discussion]
-- Various Github Issues discussing one or more of the 3 deployment parts outlined here:
- - https://github.com/keep-network/keep-core/issues/721[CircleCI Config Work]
- - https://github.com/keep-network/keep-core/issues/618[keep-client Configs to ConfigMap]
- - https://github.com/keep-network/keep-core/issues/667[Keel implementation via Terraform]
diff --git a/docs-v1/rfc/rfc-14-token-grants.adoc b/docs-v1/rfc/rfc-14-token-grants.adoc
deleted file mode 100644
index dbc8991dd6..0000000000
--- a/docs-v1/rfc/rfc-14-token-grants.adoc
+++ /dev/null
@@ -1,739 +0,0 @@
-:toc: macro
-
-= RFC 14: Token grants
-
-:icons: font
-:numbered:
-toc::[]
-
-== Background
-
-A token grant represents a gradual transfer of KEEP tokens
-from the grant creator to the _grantee_.
-The difference between these _grant tokens_ and ordinary _liquid tokens_ is
-that grant tokens cannot be transferred away from the grant
-before their ownership is fully transferred to the grantee
-according to a _vesting schedule_.
-
-In addition, some grants will be _revocable_
-so that the grant manager can _revoke_ the remaining grant
-and the remaining unvested tokens
-will return to an address specified by the grant manager.
-
-=== Use-cases and expected characteristics
-
-Keep Org uses token grants widely,
-to distribute tokens to investors and to reward employees.
-
-Investors' token grants limit the amount of liquid tokens
-that could be dumped on exchanges to make a quick profit,
-and incentivize holders to stake instead.
-A typical investor's grant vests in two years,
-but six-month and one-year grants are also used.
-Investor grants are non-revocable.
-
-Employees' token grants replace traditional startup equity,
-and need to support vesting cliffs and revocability.
-Employees' opportunities to stake early are less important
-and may even be contractually restricted
-to prevent various conflicts of interest.
-
-=== Staking token grants
-
-The grantee should be able to use their grant tokens for staking,
-but they should not be able to withdraw them prematurely.
-This presents various problems in practice.
-
-==== Tattletale transfer
-
-In the Keep network,
-staked tokens are used as collateral to enforce correct behavior.
-When staker _Alice's_ misbehavior is proven on-chain,
-some of her staked tokens will be _slashed_ as a punishment.
-Slashing can mean either _burning_ the tokens,
-effectively returning their value to all other token-holders;
-or _seizing_ the tokens to the contract imposing the punishment
-so they can be redistributed according to the contract's rules.
-
-In some cases, detecting and penalizing Alice's misbehavior
-will require collaboration from another staker, _Bob_.
-To incentivize Bob to prove Alice's misbehavior,
-the network entitles him to a _tattletale reward_,
-a fraction of Alice's slashed tokens.
-
-However, if this _tattletale fraction_ is sufficiently high,
-a new type of attack emerges:
-if Alice and Bob are secretly the same party,
-they can reclaim the tattletale reward by tattling on themselves.
-In this situation,
-a _tattletale transfer_ from Alice to Bob happens.
-
-Tattletale transfers (or _t-transfers_ for short)
-can bypass many limits ordinarily in place.
-Tokens can be transferred between stakers
-without waiting for the normal unstaking time-lock to release,
-and deterrent to misbehavior can be significantly reduced.
-With token grants, the most relevant consideration is that
-tattletale transfers could be used to extract unvested tokens from a grant.
-Any scheme for staking grant tokens
-must be able to prevent such _premature withdrawals_
-from significantly undermining the integrity of the grant.
-
-===== Limiting tattletale transfer: minimum burn fraction
-
-By burning most (e.g. 95%) of slashed tokens,
-the efficiency of tattletale transfer can be significantly constrained.
-If Alice proves Bob's misbehavior and Bob is penalized by 100 KEEP,
-at least 95 KEEP would be destroyed and at most 5 KEEP transferred to Alice.
-
-This serves two goals.
-First, Bob cannot efficiently withdraw unvested tokens
-through tattletale transfer.
-With a 95% minimum burn,
-only 1/20 of the slashed tokens can be t-transferred.
-On a 24-month grant this represents an amount
-that would vest in 1.2 months or roughly 37 days,
-at the cost of the entire rest of the grant.
-As the remaining vesting time grows shorter,
-this "advance withdrawal window" also grows narrower.
-
-Second, limiting tattletale transfer efficiency
-makes certain types of misbehavior more costly or less profitable.
-Burning tokens benefits all token-holders
-equally in proportion to how many tokens they own,
-while an adversary who expects to be caught
-can always collect the tattletale rewards
-from proving their own misbehavior.
-
-With a high tattletale transfer efficiency
-(80% for the sake of illustration)
-Alice and Bob could collaborate to misbehave and collect the tattletale reward,
-reducing the effective deterrent very significantly.
-If Alice and Bob together own 30% of the token supply,
-they would only suffer 14% of the nominal punishment:
-Alice would collect 80 KEEP as her tattletale reward
-and their remaining holdings would indirectly accrue
-30% of the value of the burned 20 KEEP (6 KEEP).
-With a 95% minimum burn Alice and Bob could only recoup 33.5%:
-5 KEEP as tattletale reward and 28.5 KEEP indirectly (95 KEEP * 0.30).
-
-Similarly, if Alice has compromised Bob's operator keys
-she could use tattletale transfer to steal Bob's stakes.
-It is desirable that compromised operators' stakes can be stolen,
-but it is also desirable to limit the fraction of the token supply
-owned by proven malicious parties.
-Some have estimated that 5% of all BTC have been stolen.
-If a similar amount of KEEP were to be stolen from compromised operators,
-with a 95% minimum burn
-the thieves would only represent 0.25% of stakeable tokens.
-
-===== Limiting tattletale transfer: locking tattletale rewards
-
-As a further obstacle to "advance withdrawals" via tattletale transfer,
-all tattletale rewards could be locked for a time
-equal to the unstaking time (e.g. 3 months).
-With a 95% minimum burn and 3 month lock on tattletale rewards,
-the amount that can be "advance withdrawn" with tattletale transfer
-is less than the amount that would vest by the time the tokens are freed
-for grants vesting in less than 60 months.
-
-==== Revocable grants and illusory stake
-
-If Alice is expecting her grant to be revoked in the near future,
-the value of her unvested tokens at that time is effectively zero.
-This _illusory stake_ significantly weakens the effective deterrent
-when staking with revocable grant tokens.
-
-==== Trusted staking contracts and upgrading them
-
-If unvested grant tokens can be staked,
-staking contracts are privileged towards grants;
-the grant contract trusts the staking contract not to behave in certain ways
-without being able to enforce it.
-If a grantee could stake their grants on arbitrary contracts,
-they could make up their own "staking contracts"
-that exploit grant staking to the maximum possible extent.
-
-This presents a problem with upgrades.
-The RFC 11 upgrade process consists of Keep Org deploying a new staking contract
-and stakers migrating their stakes by unstaking and re-staking.
-The token grant scheme must not prevent staking upgrades
-while grants are active,
-but the addresses of future staking contracts are unknown.
-
-=== Previously considered schemes
-
-==== Unlimited stake-ahead
-
-In the unlimited stake-ahead model,
-grantees can instruct the grant contract
-to stake all of their grant tokens
-by transferring an equal amount of liquid tokens to the staking contract.
-The grant contract acts as the _owner_ of the tokens;
-grantees nominate the _operator_, _beneficiary_, and _authorizer_,
-and can acquire rewards from operating with the stake as collateral.
-Upon unstaking the tokens are returned to the grant.
-
-The grant contract can be unprivileged,
-affecting only the security of tokens involved in grants,
-and no special considerations are required in the staking contract.
-However, unlimited stake-ahead provides no protection from t-transfer abuse
-or illusory stake.
-
-==== Limited stake-ahead
-
-In the limited stake-ahead model,
-grantees can only stake tokens that would vest within the unstaking time.
-The grantee can be assigned as the owner,
-as the amount of tokens that become liquid upon unstaking
-equals or is less than the amount
-they would have otherwise been able to withdraw from the grant.
-
-Limited stake-ahead preserves normal incentives with non-revocable grants
-but doesn't protect against illusory stake.
-It also places short grants in a significantly more favorable position
-as they can stake their tokens earlier.
-
-==== Grant tokens as a separate type of collateral
-
-If the special status of grant tokens is maintained when staking,
-any tattletale rewards would simply consist of another grant, vesting over time.
-This prevents premature withdrawals with t-transfer,
-but doesn't address illusory stake.
-
-Recognizing grants as valid collateral
-makes the grant contract a part of the security-critical core;
-if someone could arbitrarily manipulate the grant contract
-they would be able to create unlimited amounts of forged collateral.
-Additionally, calculating correct vesting times is complex
-as grants are split by slashing and tattletale transfers.
-
-==== Enforcing invariants with a staking proxy
-
-If a separate staking proxy is established
-between the grant contract and staking contracts,
-the grant contract could transfer liquid tokens to the proxy
-which then enforces the desired _staking invariants_
-on arbitrary staking contracts.
-This protects the integrity of grants
-by making staking contracts unprivileged,
-and the effectiveness of t-transfer could be limited by the right invariants.
-
-If the majority of slashed tokens are burned
-and only a small fraction can be seized
-and possibly used as a tattletale reward,
-t-transfer becomes dramatically less abusable.
-
-However, a staking proxy has to
-duplicate large parts of staking contract functionality,
-and cross-contract calls make staking operations more expensive.
-Behavior defined in the proxy is permanently immutable
-unless the proxy itself is upgradeable.
-
-== Proposal
-
-Non-revocable token grants are staked with unlimited stake-ahead,
-by transferring liquid tokens from the grant contract
-to a staking contract authorized by the grant's manager,
-appointed by the grant creator upon grant creation.
-Revocable grants can't be staked through the grant contract;
-instead, vested liquid tokens can be withdrawn and staked normally.
-
-_Authorized staking contracts_ are assumed to enforce the invariants
-a particular grant's manager wants enforced.
-For the use of Keep Org's grants,
-this consists of a _minimum burn fraction_ of 95%:
-when a staker is slashed,
-at least 95% of the tokens are burned and at most 5% are seized.
-
-Authorized staking contracts are identified
-using a two-role authorization from RFC 11:
-the grant manager can authorize contracts from a global master list
-of staking contracts sanctioned by the governance structure.
-
-Upgrades to staking contracts are accommodated
-by providing a way for the grant contract
-to pass arbitrary instructions from the grantee to the staking contract.
-
-=== Goal
-
-Unprivileged grant contract::
-The security of the Keep network as a whole should be unaffected
-even if the grant contract were to execute arbitrary malicious code.
-
-Upgradeable staking contract::
-The grant scheme should not prevent future improvements to the staking scheme
-as defined in RFC 11.
-
-Fair grant staking::
-The recipient of a non-revocable grant
-should be able to stake with the full grant.
-A grant's vesting schedule should only determine
-the amount of liquid tokens the grantee could withdraw at a given time.
-
-Limited tattletale transfer::
-Abusing tattletale transfer to violate the rules of a token grant
-should provide little benefit at a significant cost.
-
-No illusory stake::
-The need for a reliable deterrent to misbehavior is prioritized
-over revocable grantees' opportunity to obtain staking rewards.
-
-=== Implementation
-
-A token grant represents a gradual transfer of KEEP tokens
-from the creator of the grant to the _grantee_ (grant recipient).
-
-A token grant is characterized by its _basic parameters_
-and its _vesting schedule_.
-
-==== Basic parameters
-
-The basic parameters of a token grant
-include the _grant manager_,
-the _grant recipient_,
-the _grant amount_
-and the _revocability_ of the grant.
-
-Grant manager::
-The address appointed to manage the grant.
-If the grant is irrevocable,
-the grant manager may determine the _authorized staking contracts_
-the grant can be staked on.
-If the grant is revocable,
-the grant manager may revoke the grant.
-
-Grant recipient::
-The address of the party receiving the grant.
-The recipient may withdraw vested tokens from the grant,
-or stake non-revocable grant tokens.
-
-Grant amount::
-The number of tokens involved in the grant.
-
-Revocability::
-Whether the grant is revocable (_True_) or non-revocable (_False_).
-
-===== Revocability
-
-Token grants may be _revocable_ or _non-revocable_.
-A non-revocable grant represents an irreversible transfer of tokens
-that, once initiated, cannot be stopped or altered.
-A revocable grant represents a conditional transfer,
-subject to continuing consent of the grant manager.
-The grant manager can revoke a revocable grant at any time.
-If a grant is revoked,
-all unvested tokens are returned to an address specified by the grant manager.
-Vested tokens remain in the grant
-and are available for the grantee to withdraw.
-
-==== Vesting schedule
-
-Tokens in a grant are locked until _vested_
-according to a linear schedule defined by
-the _starting time_,
-_grant duration_
-and the _vesting cliff_.
-
-Tokens in the grant start vesting at the starting time,
-becoming available for withdrawal gradually over the grant duration.
-The vesting cliff denotes the earliest time
-tokens can be withdrawn from the grant.
-
-Vested tokens that aren't otherwise in use
-can be withdrawn at the grantee's discretion.
-
-Starting time::
-The time the grant begins vesting.
-The starting time of a grant
-may differ from the exact time the grant creation transaction is processed.
-
-Grant duration::
-Time after starting until the grant is fully vested
-and all tokens may be withdrawn.
-
-Vesting cliff::
-The earliest time after starting tokens can be withdrawn from the grant.
-
-==== Creating a token grant
-
-A token grant is created by submitting a transaction
-defining the _basic parameters_ and the _vesting schedule_,
-and transferring the _grant amount_ of tokens to the grant contract.
-
-===== Example
-
-Alice wants to transfer 1,000 KEEP to Bob and Carol each.
-Bob should receive his tokens over 12 months,
-and be able to start withdrawing tokens after 1 month.
-Carol's grant should be revocable,
-lasting 24 months with a 6 month vesting cliff.
-
-----
-Grant 1
-Manager: Alice
-Recipient: Bob
-Amount: 1,000 KEEP
-Starting time: T_0
-Duration: 12 months
-Vesting cliff: 1 month
-Revocable: False
-
-Grant 2
-Manager: Alice
-Recipient: Carol
-Amount: 1,000 KEEP
-Starting time: T_0
-Duration: 24 months
-Vesting cliff: 6 months
-Revocable: True
-----
-
-==== Grant status
-
-When a grant is created,
-all grant tokens start unvested and unstaked.
-
-Over time, grant tokens will vest
-and become available for withdrawal as liquid tokens.
-_Vesting status_ is calculated implicitly
-from the vesting schedule and the current time.
-
-Grant tokens can be withdrawn once vested.
-Non-revocable grant tokens can also be staked,
-and staked tokens can be lost as punishment.
-The _usage status_ of a grant's tokens tracks these developments.
-
-===== Vesting status
-
-All grant tokens are either _vested_ or _unvested_.
-The vested amount at some time
-represents the maximum number of tokens that may be withdrawn at that time.
-Grant tokens vest linearly over the grant duration;
-when half of the grant duration has elapsed
-50% of the grant tokens will have vested, and so on.
-However, until the vesting cliff is reached,
-the number of vested tokens is fixed at zero.
-
-The amount of vested tokens at time `time_now` is calculated as follows:
-
-[source, python]
-----
-time_elapsed = time_now - time_starting
-cliff_reached = time_now >= vesting_cliff
-
-if cliff_reached:
- vested_fraction = time_elapsed / grant_duration
-else:
- vested_fraction = 0
-
-vested_tokens = grant_amount * vested_fraction
-----
-
-3 months in, Bob's vesting cliff has been reached,
-so the amount of vested tokens in Bob's grant equals
-`1000 KEEP * (3 months / 12 months) = 250 KEEP`.
-Carol's 6-month vesting cliff has not been reached;
-if it had, her grant would have
-`1000 KEEP * (3 months / 24 months) = 125 KEEP`
-available for withdrawal.
-
-===== Usage status
-
-The _usage status_ of a grant's tokens consists of
-_available_, _withdrawn_, _staked_, and _slashed_;
-all grant tokens fall within one of these categories.
-
-_Withdrawn_ means tokens that have vested
-and been withdrawn from the grant as liquid tokens.
-The number of withdrawn tokens is tracked in its own entry,
-which is updated whenever a successful withdrawal is performed.
-
-_Staked_ grant tokens are actively being used
-as collateral for staking.
-The number of staked tokens is calculated
-by summing the _staked amount_ in each individual _grant stake_ of the grant.
-
-_Slashed_ grant tokens were staked and have been lost in a penalty.
-The grant tracks the number of slashed tokens explicitly.
-When a grant stake has finished unstaking and its tokens are returned,
-the difference between the returned amount and the original stake
-is added into the slashed tokens.
-With revocable tokens, the _slashed_ status is used for revocation.
-
-Tokens in the grant that aren't _withdrawn_, _staked_, or _slashed_
-are _available_ by default.
-Available grant tokens can be withdrawn if the vesting schedule permits,
-or staked if the grant is non-revocable.
-The number of available grant tokens is calculated
-by subtracting _withdrawn_, _staked_ and _slashed_ tokens
-from the grant amount.
-
-===== Grant stakes
-
-When non-revocable grant tokens are staked,
-some relevant information is stored in a _grant stake_ entry.
-Each non-revocable grant maintains a list of its grant stakes.
-
-A grant stake entry includes
-the _staking contract_ used for the stake,
-the _operator address_ of the stake,
-and the _staked amount_ originally transferred to the staking contract.
-Grant stakes can be uniquely addressed by the pair
-`(staking_contract, operator_address)`.
-
-A grant stake entry is erased
-when its corresponding stake has finished unstaking
-and its tokens are successfully returned to the owner.
-
-==== Grant records
-
-Each token grant is stored in the _grant contract_ as a _grant record_.
-The grant record consists of the following:
-
-* Basic parameters:
- * _grant manager_
- * _grant recipient_
- * _grant amount_
- * _revocability_
-* Vesting schedule:
- * _creation time_
- * _grant duration_
- * _vesting cliff_
-* Grant status records:
- * _withdrawn tokens_
- * _slashed tokens_
- * _grant stakes_
-
-==== Staking token grants
-
-Non-revocable token grants are staked
-by instructing the grant contract to stake them
-with an _operator_, _beneficiary_ and _authorizer_ appointed by the _grantee_.
-The grant contract acts as the _owner_ of the stake.
-
-Both vested and unvested tokens can be staked
-and the rewards collected by the grantee.
-
-==== Authorized staking contracts
-
-In the _authorized staking contracts_ model,
-grants can be staked in any staking contract
-that has been approved by the _grant authorizer_.
-The _grant authorizer_ is expected to audit new staking contracts
-and verify that they enforce the desired invariants adequately,
-before approving them for staking grants.
-
-When a staking contract has been approved,
-the grant contract will trust it to enforce the staking invariants
-and any grantee can direct the grant contract
-to stake some or all of their _available tokens_
-(not already staked or withdrawn) in the grant.
-The grant contract will then transfer the specified amount of tokens
-to the staking contract,
-along with all other necessary information.
-The stake is recorded in the grant contract,
-and the staked amount subtracted from the _available tokens_ in the grant.
-
-The grant contract takes the role of the _owner_ in the staking contract,
-while the _operator_, _beneficiary_ and _authorizer_
-are defined by the _grantee_.
-Any rewards or punishments to the staker are applied in the staking contract,
-without involving the grant contract in any way.
-
-When the grantee wishes to unstake,
-they direct the grant contract
-to unstake and reclaim the remaining tokens.
-Unstaking and reclaiming tokens
-terminates the staker relationship between the _owner_ and _operator_,
-and all remaining stake is returned to the _owner_.
-Therefore, if the _returned amount_ is less than the original _staked amount_,
-the difference has been slashed in punishment
-and is recorded in the grant contract as such.
-Redelegating grant stakes is not supported.
-
-===== Option A: registry master as grant authorizer
-
-In option A,
-any staking contract listed on the _registry_
-as a _sanctioned staking contract_
-is automatically authorized for grant staking.
-
-If the role of the _registry master_ is compromised,
-arbitrary "staking contracts" can be authorized.
-Existing stakes on legitimate staking contracts are unaffected,
-but unstaked irrevocable grants can be emptied.
-
-===== Option B: global grant authorizer
-
-In option B,
-the grant contract has its own _grant authorizer_ role,
-approving staking contracts for all grantees.
-All grants share the same authorized staking contracts,
-ensuring that the disappearance of the grant manager
-does not prevent grantees from staking on new contracts.
-
-A staking contract can be approved by the grant authorizer
-only if it has been _sanctioned_ on the registry.
-The authorizations in Option B are similar to
-how _service contracts/gateways_ are managed in RFC 11.
-As in RFC 11, the compromise of neither the _registry master_
-nor _grant authorizer_ alone can compromise token grants;
-both must be compromised simultaneously.
-
-===== Option C: grant manager as grant authorizer
-
-In option C,
-_grant managers_ authorize staking contracts
-for all grants they manage.
-Grants with the same _grant manager_
-share the same authorized staking contracts.
-
-Like in option B,
-staking contracts must be _sanctioned_ to be authorized.
-
-==== Operations on grants
-
-===== Withdrawing tokens
-
-_Vested_ tokens that haven't already been _withdrawn_
-can be withdrawn at the discretion of the grantee, if tokens are available.
-The amount of tokens that can be withdrawn at a point in time
-equals `min(available, (vested - withdrawn))`.
-
-To withdraw, the _grantee_ requests a withdrawal
-and specifies a _withdrawal amount_.
-
-If the _withdrawal amount_ is equal or less than
-the _maximum withdrawal_ at the time,
-the grant contract will add _withdrawal amount_ to the _withdrawn_ tokens
-and send the grantee _withdrawal amount_ tokens.
-
-If the _withdrawal amount_ exceeds the _maximum withdrawal_,
-the withdrawal will fail.
-
-===== Staking tokens
-
-_Available_ tokens can be staked regardless of vesting status.
-
-To stake, the _grantee_ specifies a _staking amount_,
-the _staking contract_ to stake in,
-and the _operator_, _beneficiary_ and _authorizer_.
-The grantee must also provide a signature from the _operator_
-to operate for the _grant contract_ as the _owner_.
-
-The _staking amount_ must be
-equal or less than the number of _available_ tokens.
-The _staking contract_ must be approved by the applicable _grant authorizer_.
-If either condition is not satisfied, the staking request will be rejected.
-If both conditions are satisfied,
-the grant contract will attempt to stake _staking amount_ tokens
-at the _staking contract_,
-using the supplied _operator_, _beneficiary_ and _authorizer_ addresses.
-
-The _grant stake_,
-consisting of the triplet `(staking_contract, operator, staking_amount)`,
-is recorded in the grantee's _grant stakes_.
-The _staking amount_ is added to _staked_ tokens of the grant,
-reducing the _available_ tokens by the same amount.
-
-===== Unstaking a grant stake
-
-At any time, the grantee can request any _grant stake_ to be unstaked.
-To unstake, the grantee specifies the _staking contract_ and _operator_
-of the _grant stake_ they wish to initiate unstaking on.
-
-If the combination of _staking contract_ and _operator_
-matches an active _grant stake_ of the grantee,
-the grant contract will request the _staking contract_ to initiate unstaking.
-Otherwise, the grant contract will ignore the request.
-
-===== Reclaiming tokens from an unstaked grant stake
-
-At any time, the grantee can request any _grant stake_ to be reclaimed.
-The grantee specifies the _staking contract_ and _operator_
-of the relevant _grant stake_.
-
-If the grantee has a matching _grant stake_,
-the grant contract will request the _staking contract_
-to return unstaked tokens.
-Otherwise, the grant contract will ignore the request.
-
-If reclaiming the tokens fails,
-the grant contract will assume the stake had not finished unstaking
-and will not modify the _grant stake_ information.
-
-If reclaiming the tokens succeeds,
-the grant contract will note the _returned amount_.
-If the _returned amount_ matches the original _staking amount_,
-the _returned amount_ is subtracted from _staked_ grant tokens
-and added to _available_ grant tokens.
-If the _returned amount_ is less than the original _staking amount_,
-the _difference_ is added to _slashed_ grant tokens,
-the _staking amount_ is subtracted from _staked_ grant tokens,
-and the _returned amount_ is added to _available_ grant tokens.
-In either case, the _grant stake_ is removed.
-
-===== Revoking the grant
-
-A revocable grant can be revoked at any time by the grant manager.
-Revoking a grant slashes its unvested tokens,
-transferring them to an address specified by the manager.
-
-Grants are revoked by submitting a transaction
-specifying the grant to be revoked
-and the recipient address.
-
-The grant contract checks that the grant exists,
-is revocable,
-and the transaction was sent by the grant manager.
-
-A revocable grant cannot be staked,
-so the slashed amount on a revocable grant shows whether it has been revoked.
-If the grant already has slashed tokens,
-it has been revoked earlier and the repeat revocation is ignored.
-
-If the checks pass,
-the amount of unvested tokens in the grant is calculated.
-The _unvested amount_ is added to the _slashed_ grant tokens
-and transferred to the recipient address.
-
-=== Limitations
-
-Without TATTLETALE_LOCK,
-grantees can abuse t-transfers to withdraw more than the vested amount
-although at the expense of the remaining grant
-
-Even with TATTLETALE_LOCK, revocable grants can still be overwithdrawn
-if any level of stakeahead is permitted
-
-=== Proof of Concept
-
-If you have PoC code, refer to the relevant branch and give a brief summary.
-
-== Future Work (optional)
-
-If applicable, what future evolutions could you see this approach leading to?
-Particularly if these possibilities influenced your thinking about the main
-proposal, this is important.
-
-== Open Questions (optional)
-
-Should TATTLETALE_LOCK be implemented,
-or is the loss of MINIMUM_BURN_FRACTION sufficient
-to disincentivize tattletale transfer
-
-How to deal with revocable grants:
-unlimited stakeahead as with non-revocables,
-limited stakeahead,
-or no staking of unvested tokens at all
-
-[bibliography]
-== Related Links
-
-- Flowdock Links
-- Other links
-- If you have publications, you can include them in bibliography style. If you
- start your bullet with an id in _triple_ square brackets (e.g. `+[[[AAKE]]]+`),
- you can reference it in the content body using regular cross-reference syntax
- (e.g. `+<>+`).
diff --git a/docs-v1/rfc/rfc-15-slashing.adoc b/docs-v1/rfc/rfc-15-slashing.adoc
deleted file mode 100644
index f6f99a10ff..0000000000
--- a/docs-v1/rfc/rfc-15-slashing.adoc
+++ /dev/null
@@ -1,447 +0,0 @@
-:toc: macro
-
-= RFC 15: Slashing
-
-:icons: font
-:numbered:
-toc::[]
-
-== Background
-
-To incentivize correct behavior in the Keep network,
-misbehaving participants need to be punished.
-In some situations,
-proving misbehavior requires cooperation from another participant,
-a _tattletale_.
-This coordination is incentivized by rewarding the _tattletale_
-by granting them a fraction of the tokens
-taken from the misbehaving participant.
-
-== Proposal
-
-=== Goal
-
-Slashing should be simple to implement and reason about.
-The slashing method should implement the tattletale transfer mitigations
-defined in the link:rfc-14-token-grants.adoc[token grant RFC],
-always burning at least 95% of the penalty amount.
-
-To protect staker funds,
-only authorized operator contracts should be able to punish an operator.
-
-=== Implementation
-
-Tokens are staked by transferring them to the staking contract.
-The staking contract tracks the stake allocated to each _staker_.
-Stakes can be _slashed_ to punish misbehavior.
-Tokens backing slashed stakes are burned;
-if a tattletale proves another operator's misbehavior
-they will receive 5% of the slashed tokens,
-the remainder being burned.
-
-When an operator is punished for misbehavior,
-they should generally be removed
-from the group/keep the misbehavior occurred in.
-
-==== Authorization
-
-_Operator contracts_ are authorized to impose penalties
-by stakers' _authorizers_.
-All stakers using the same _authorizer_
-share the set of authorized operator contracts.
-Once given, this authorization cannot be revoked by the authorizer.
-
-When a staker wishes to join a group
-the contract responsible for creating the group
-must be authorized by the staker's authorizer.
-The operator contract must check its authorization status
-when determining a staker's eligibility.
-
-In the random beacon a staker's eligibility is checked
-when tickets are submitted;
-this means that authorization must be checked
-when validating a ticket.
-If an operator submits a ticket to an unauthorized operator contract,
-the ticket must be rejected as invalid.
-
-==== Penalties
-
-When an operator misbehaves on-chain,
-the operator contract calls the staking contract to punish the operator.
-The staking contract checks
-that the operator contract is authorized to punish the staker,
-and if true, applies the penalty.
-
-A penalty can be applied to one or more stakers simultaneously.
-Each affected staker is penalized by the same amount.
-
-===== Pure slashing
-
-When misbehavior is detected without third-party input,
-a _pure slashing_ penalty is applied.
-Pure slashing means that the staking contract
-subtracts the applicable penalty from the operator's stake
-and burns tokens equal to the penalty amount.
-
-===== Seizing
-
-When a tattletale proves another operator's misbehavior,
-a fraction of the penalty amount is _seized_ and transferred to the tattletale,
-while the rest is burned.
-The tattletale reward can be set to any value
-between 0 and the maximum of 5% of the penalty.
-
-To apply a seizing penalty,
-the operator contract includes the tattletale operator's address in the call.
-The staking contract subtracts the applicable penalty from the operator's stake
-and transfers the reward to the tattletale's _beneficiary_ address.
-The remainder is burned.
-
-===== Penalty amounts
-
-Penalties for misbehavior could be adjusted
-to match the severity of the misbehavior.
-However, initially a simple rule should be sufficient:
-when `op_contract` imposes a punishment,
-the amount slashed should equal
-the minimum stake required to participate in operations on `op_contract`.
-If contract _Foo_ requires 10,000 KEEP to participate with one virtual staker,
-_Foo_ should slash a misbehaving virtual staker by 10,000 KEEP.
-
-==== Interface requirements
-
-===== Staking contract: slashing
-
-`slash(tokens sum, address[] misbehavers)`::
-
-Check that `msg.sender` is authorized
-to slash each `misbehaver` in `misbehavers`:
-`isAuthorized(msg.sender, misbehaver.authorizer) == true`.
-+
-Subtract `sum` tokens from the stake of each `misbehaver`
-and burn `sum * length(misbehavers)` tokens.
-
-`seize(tokens sum, float pay, address tattletale, address[] misbehavers)`::
-
-Check that `msg.sender` is authorized
-to slash each `misbehaver` in `misbehavers`:
-`isAuthorized(msg.sender, misbehaver.authorizer) == true`.
-
-Check that `0 < pay <= 1`.
-
-Subtract `sum` tokens from the stake of each `misbehaver`;
-set `total = sum * length(misbehavers)` and `reward = total * 0.05 * pay`;
-burn `total - reward`; transfer `reward` to beneficiary of staker `tattletale`.
-
-===== Staking contract: authorizations
-
-`authorize(address op_contract)`::
-
-Authorize `op_contract`.
-Operators using `msg.sender` as their authorizer
-may now join operations on `op_contract`
-and `op_contract` may slash their stakes.
-
-`isAuthorized(address op_contract, address by) -> bool`::
-
-Check if the authorizer `by` has authorized `op_contract`.
-
-===== Token contract
-
-`burn(amount sum)`::
-
-Any address that holds tokens can call `burn(amount sum)`
-to burn `sum` tokens, limited by tokens held by the address.
-
-=== Misbehavior and penalties in the Random Beacon
-
-==== DKG
-
-===== Invalid ticket
-
-An operator might submit an invalid ticket in the DKG.
-
-Invalid tickets are detected automatically
-without the need for a tattletale.
-
-Proof of invalid tickets is _objective_,
-as all information required to verify tickets is available on-chain.
-
-Because the cost of ticket submission is paid by the submitter,
-the ticket can be simply rejected and the transaction reverted.
-
-===== Failure to produce a DKG result
-
-The created group might fail to produce a valid result.
-
-Failure to finish DKG is verifiable without additional proof,
-but requires a trigger transaction for this verification
-after the deadline for completing DKG has passed.
-If no other trigger transaction is made,
-the trigger transaction for another DKG shall check
-if the previous attempt at DKG has failed to produce a result.
-
-Failure to finish DKG is _objective_.
-
-Failure to produce a result means
-that a honest and available majority
-was not present in the DKG for some reason or other.
-The precise reasons can be unpredictable.
-Failing to finish DKG is inherently punished
-by the opportunity cost of not getting into a signing group
-despite having paid the ticket submission fees.
-Because of this,
-failure to produce a valid DKG result should not be separately penalized
-without further examination of the possible causes of failure
-and the effects of collective punishment.
-
-===== Submitting an invalid DKG result
-
-An operator might submit an invalid result for the DKG.
-
-Invalid DKG results are detected automatically.
-
-Proof of invalid DKG results is _objective_.
-
-Because the cost of verifying a DKG result is paid by the submitter,
-and the submitter is reimbursed only for valid results,
-submitting invalid results inherently punishes itself
-and no further penalty is needed beyond reverting the transaction.
-
-===== Inactivity in DKG
-
-An operator might fail to send a required message during DKG.
-This lowers the effective safety margin of the group
-against lynchpinning and inability to produce a signature.
-
-Inactivity in DKG is determined by
-the list of inactive members in the DKG result submission.
-
-Unless DKG is performed on-chain,
-proof of inactivity in DKG is _subjective_
-and subject to the honest majority assumption;
-a dishonest majority could always forge a false proof of inactivity.
-It is not possible to make off-chain DKG inactivity objectively provable.
-
-Inactive members shall be removed from the group,
-but not otherwise punished;
-the opportunity cost of not being included in the group
-already provides an incentive to be active.
-
-===== Disqualification in DKG
-
-An operator might misbehave in a variety of ways during DKG.
-Active misbehavior can lower the effective safety margin of the group
-against frontrunning, lynchpinning, or signature failure.
-
-Disqualification in DKG is determined like inactivity,
-by the list of disqualified members being included in the result submission.
-
-On-chain proof of disqualification is _subjective_
-and a dishonest majority could forge a false proof.
-
-Punishing disqualified members based on subjective proof
-creates opportunities for dishonest majorities
-to attack other stakers
-in a way which extends beyond the damage caused by frontrunning the beacon.
-Because of this,
-punishing disqualified members without objective proof
-requires further examination of the associated risks and incentives.
-
-For the first version,
-disqualification shall be treated like inactivity
-and only punished with removal from the group.
-
-==== Signing
-
-===== Invalid signature share
-
-An operator may broadcast an invalid signature share to other operators
-when reconstructing the threshold signature.
-
-Invalid signature shares can only be detected on-chain
-if a tattletale submits a proof
-that includes the signature share and the information required to verify it.
-
-In the first version,
-the infrastructure for verifying these proofs is not yet in place.
-Invalid signature shares shall be simply rejected by the other members.
-
-===== Failing to broadcast a signature share
-
-When a signing group is tasked with producing an entry,
-its members are expected to broadcast signature shares.
-An operator might fail to broadcast its signature share,
-either due to actual inactivity
-or as an attempt to gain a lynchpin position and guaranteed submitter reward.
-
-Failure of an individual member to broadcast a signature share
-can not be reliably detected on-chain,
-even in the event the group as a whole fails to produce a signature.
-Thus, individual failures to broadcast shares shall not be punished.
-
-===== Submitting an invalid signature
-
-An operator may submit an invalid threshold signature on-chain
-when generating a beacon entry.
-
-Invalid signatures are automatically detected.
-
-Proof of an invalid threshold signature is _objective_.
-
-As verifying a threshold signature is relatively expensive,
-no separate punishment is needed beyond reverting the transaction.
-
-===== Unauthorized use of individual private key
-
-An operator's individual private key may be leaked
-and used inappropriately.
-
-Unauthorized use of a member's individual private key
-can be proven on-chain by the submission of a suitable proof.
-
-The first version is not yet able to verify these proofs,
-so unauthorized use of individual private keys is not separately penalized.
-
-===== Creating an unauthorized signature
-
-An entire signing group's private key could be abused
-to create an unauthorized signature.
-
-Unauthorized threshold signing can be proven by publishing
-a value the group hasn't been previously requested to sign,
-and a valid signature for the value.
-
-Proof of unauthorized signing is _objective_.
-
-Unauthorized signing shall be punished
-by _seizing_ tokens from all members,
-with the submitter of the proof as the _tattletale_.
-
-===== Failure to produce a signature
-
-A signing group may fail to produce a new entry within the deadline.
-
-Failure to generate an entry can be verified on-chain without a separate proof,
-but requires a transaction to trigger this check.
-
-The proof of failure is _objective_.
-
-When a group fails to produce an entry,
-all of its members shall be subject to _seizing_
-and the group itself shall be terminated.
-The submitter of the trigger transaction shall be treated as the _tattletale_,
-but the tattletale reward shall be limited to
-`min(1, 20 / group_size)` of the maximum,
-or effectively the minimum stake of a single member.
-This is to prevent actors in a lynchpin position
-from profitably stealing other stakers' funds.
-
-=== Limitations
-
-Slashing is not limited to the amount originally staked
-for participating in the relevant operations;
-a malfunctioning operator contract could cause a staker to lose all stake.
-
-Chain reorganizations may lead to honest behavior in one branch
-being punishable misbehavior in another.
-Mitigations for this have not been included in this RFC.
-
-== Future Work
-
-With a different staking paradigm
-that tracks individual keep and group memberships,
-it is possible to limit the risk
-from malfunctioning operator contracts or trusted applications
-to the stake actually corresponding to the operations.
-
-=== Authorization
-
-This RFC doesn't cover authorizing individual keeps,
-or situations where a trusted application
-has the authority to impose a penalty.
-
-Because authorizations cannot be revoked,
-operator contracts can safely cache positive authorization
-after the first lookup to the staking contract.
-Lack of authorization cannot be cached,
-as the operator contract could later become authorized.
-
-=== Punishments
-
-==== DKG
-
-===== Failure to produce a DKG result
-
-Punishing the failure to produce a DKG result
-has interesting implications that could be explored further.
-
-===== Disqualification in DKG
-
-Punishing disqualified DKG members on subjective proof
-creates opportunities to attack honest stakers
-but can also provide a way for compromised groups
-to profitably reveal and remove themselves
-if seizing on subjective proof is permitted.
-The implications and tradeoffs of
-concentrated vs. distributed risk are interesting.
-
-However, disqualification is defined by there being _objective_ off-chain proof,
-so the operator contract could be made to verify DKG transcripts
-to render DKG disqualification _objective_ on-chain as well.
-
-Disqualified members must be removed from the group.
-If disqualification is objectively proven,
-the operator must be punished with _seizing_ their stake.
-The submitter of the transaction containing the DKG transcript
-shall be the _tattletale_.
-
-==== Signing
-
-===== Invalid signature share
-
-Invalid signature shares can only be detected on-chain
-if a tattletale submits a proof
-that includes the signature share and the information required to verify it.
-If the DKG result includes a merkle root
-of each member's individual public key,
-this proof can be relatively compact and inexpensive to verify.
-
-Proof of an invalid signature share is _objective_.
-
-If the broadcast of an invalid signature share is proven
-the responsible operator shall be punished by _seizing_,
-with the submitter of the proof receiving the tattletale reward.
-
-===== Unauthorized use of individual private key
-
-Unauthorized use of a member's individual private key
-can be proven on-chain by the submission of a suitable proof.
-The proof must contain the DKG merkle root,
-a merkle path to the individual public key,
-some value that isn't a requested entry,
-and a valid signature of that value with the individual public key.
-
-Such proof is _objective_.
-
-Unauthorized use of an individual private key
-shall be punished by _seizing_,
-with the submitter of the proof as the _tattletale_.
-
-=== Chain reorganizations
-
-When chain reorganizations happen,
-a honest entry generation in one branch
-can be indistinguishable from frontrunning in the other.
-It is easy to punish the generation of unauthorized threshold signatures
-on values that aren't a part of the entry chain,
-and this can serve as a way to incentivize actors
-that have compromised the group private key of some group
-to destroy the group for immediate profit
-instead of covertly frontrunning the beacon.
-However, actual frontrunning is more difficult to deal with.
-
-[bibliography]
-== Related Links
-
-- link:rfc-14-token-grants.adoc[RFC 14: Token grants]
diff --git a/docs-v1/rfc/rfc-16-pricing.adoc b/docs-v1/rfc/rfc-16-pricing.adoc
deleted file mode 100644
index 60806360c5..0000000000
--- a/docs-v1/rfc/rfc-16-pricing.adoc
+++ /dev/null
@@ -1,551 +0,0 @@
-:toc: macro
-
-= RFC 16: Pricing
-
-:icons: font
-:numbered:
-toc::[]
-
-== Background
-
-The beacon needs to capture enough value to make it self-sufficient.
-A method for pricing beacon entries is required,
-but many schemes have serious drawbacks
-or can be broken by relatively simple third-party contracts.
-
-== Proposal
-
-Beacon entries are priced
-based on a _cost estimate_ which covers entry verification and DKG,
-and a _profit margin_ that scales linearly in group size.
-An interface is provided
-for customer applications to query the current _entry fee estimate_.
-The customer may provide a callback to receive the entry,
-and ensure they provide a sufficient _callback allowance_
-to cover the gas fees of the callback.
-Any surplus is returned to the customer.
-
-When a valid entry is submitted,
-the submitter receives a _submitter reward_
-and every other member in the signing group receives a _group reward_.
-To incentivize submitting an entry,
-the _submitter reward_ increases as a request goes unserved
-while the _group reward_ diminishes.
-Rewards not paid out to the operators
-are paid out to requesters to subsidize new requests.
-
-=== Goal
-
-A simple method for pricing beacon entries
-that doesn't present easy exploitation opportunities.
-The pricing method should avoid
-the known downfalls of previously considered, more complex, schemes,
-such as price discrimination being defeated by callback pooling.
-
-=== Implementation
-
-==== Making requests
-
-When a customer wishes to receive an entry,
-they should query the beacon for the _entry fee estimate_
-applicable for their request:
-`entry_fee_estimate = estimate_fee(callback_gas_amount)`.
-The _callback gas amount_ is the amount of gas required
-for the customer's callback to execute successfully;
-if no callback is required `callback_gas_amount = 0`.
-
-The estimate returned is guaranteed to be valid
-only for the transaction it is called in,
-and for callback gas costs
-equal or lower than the provided callback gas amount.
-Thus the request should be made immediately after receiving the estimate.
-Paying more than the applicable entry fee estimate
-has a minimal cost to the requester
-as excess fees will be refunded.
-Insufficient payment will lead to the request being rejected
-and the transaction reverted.
-
-To make a request after determining the applicable fee
-the customer must call the request method on the beacon,
-transferring enough currency to cover the fee:
-`request_entry.value(entry_fee_estimate)()`.
-
-If the customer wishes to receive the generated random number in a callback,
-they should also specify the _callback address_, _callback function_,
-and _callback gas amount_:
-`request_entry.value(entry_fee_estimate)(callback_address, callback_function, callback_gas)`.
-
-No new requests should be made
-while the beacon is already processing another request.
-Requests made while the beacon is busy will be rejected
-and the transaction reverted.
-
-==== Receiving a request
-
-If the beacon is already serving an earlier request,
-it rejects any new requests
-(implicitly refunding the fees by reverting the transactions).
-
-When the beacon is non-busy and receives a request,
-it first checks that the _request fee_ exceeds
-the _entry fee estimate_ with the _callback gas amount_ from the request.
-
-Once the request has been verified to be sufficiently funded,
-the beacon select the new signing group.
-The selected group is tasked with producing the new entry.
-
-The request is set as the _pending request_
-including the following information:
-
-- the _requester address_
-
-- the _callback address_, _callback function_, and _callback gas amount_, if applicable
-
-- the _assigned signing group_{blank}footnote:[This is needed
-if changes to the active groups can be made
-while waiting for an entry.
-]
-
-- the _submission delay base time_ which equals
-the number of the block the request was received in,
-plus 1{blank}footnote:[The way of calculating rewards
-is inevitably prone to off-by-one errors _somewhere_
-and doing the incrementing at request time seems the simplest.
-]
-
-- the _estimated gas price_ at the time of the request{blank}footnote:[This
-means we don't need to assume the price feed remains stable
-between the making of the request and the paying out of rewards.
-If the gas price feed is guaranteed to not change
-until a valid entry is received, this is not necessary.
-]
-
-- the _request fee_ paid
-
-==== Serving a request
-
-===== Receiving submissions
-
-When the assigned signing group has produced a valid entry,
-one of its members should submit it to the beacon.
-The first member to submit a valid entry is the _submitter_.
-_Submission deadline_ is the block number before which the
-valid entry must be submitted.
-
-Submissions that fail verification are ignored.
-Repeat submissions for a request that has already been served
-should be dropped immediately,
-minimizing the gas expenditure.
-
-If no valid entry has been received by the _submission deadline_,
-a submission timeout can be called by anyone.
-If the submission times out,
-the failing group is terminated and its members slashed.
-A new signing group is assigned from the remaining active groups
-and the submission delay calculation is reset
-by setting the _submission delay base time_
-to the previous _submission deadline_.
-
-When a valid entry submission is received on-chain
-it is emitted in an event,
-the requester's callback is called if applicable,
-and fees, rewards and refunds are paid out.
-
-===== Callback processing
-
-If the requester specified a callback,
-the callback is called using the callback gas amount as the maximum gas.
-
-If the callback gas amount turns to be not enough to execute the callback,
-callback execution is skipped and the rest of the relay entry submission code
-is processed as usual.
-
-After the callback is made
-the amount of gas spent on the call
-is multiplied with the lower of the
-_estimated gas price_ at the time of the request,
-or the actual gas price of the transaction,
-to get the _callback expenditure_.
-
-The minimum of the gas price protects the beacon and requester against
-malicious miner-submitters.
-
-If the submitter is also a miner, they can place any arbitrary gas
-price on the transaction. If the gas price used for calculating the callback
-expenditure is higher than the quoted amount and the amount of gas used on the
-call is close to the maximum specified by the requester, the requester refund
-can go negative. If the negative requester refund is added to the 1% surplus
-pool subsidy it can permit the miner-submitter to steal the subsidy.
-
-On the other hand, if the amount of gas spent on the callback is less than the
-provided maximum, a miner submitter can set the gas price to such an amount that
-the requester is billed for the entire gas budget even if they really only spent
-a small fraction of it. This means a miner submitter can steal the requester's
-refund.
-
-If the callback execution uses more gas than specified in the request, it should
-run out of gas. Thus the only scenario where the callback execution can cost more
-than was quoted and paid for, is when the gas cost of the transaction exceeds the
-quoted estimate (which includes the safety margin mentioned in the gas price feed
-section). The submitter is intended to take the hit for submitting with a gas price
-that exceeds the estimate.
-
-===== Requester refund
-
-After the _callback expenditure_ has been determined,
-it is added to the _entry base price_ calculated with the _estimated gas price_
-to get the _actual entry price_.
-If no callback was specified in the request the _callback expenditure_ is 0
-and the _actual entry price = entry base price_.
-
-The difference between the actual entry price and the _requester fee_
-is refunded to the requester,
-along with 1% of the _request subsidy pool_ of the beacon.
-
-===== Paying rewards and operational fees
-
-The _entry base price_ consists of:
-the beacon's nominal _profit margin_ for the entry;
-a _DKG contribution_ to cover the cost of creating new signing groups,
-amortized over multiple entries per DKG;
-and the _entry verification fee_ for the gas costs of entry submission.
-
-The submitter and other group members are rewarded
-based on the _submission delay_;
-time from the _submission delay base time_
-to the submission of the valid entry.
-The rewards are specified in their own section.
-
-If the sum of rewards paid out
-is less than the _profit margin + entry verification fee_,
-the difference is added to the _request subsidy pool_.
-
-The _DKG contribution_ is added to the _DKG fee pool_,
-and the state of the pool is checked.
-If the amount in the DKG fee pool equals or exceeds the _DKG cost estimate_,
-group creation and a new DKG may be triggered.footnote:[Whether
-DKG is actually triggered is open.
-Always triggering DKG when the fee pool reaches a given level
-doesn't smooth out fluctuations in demand:
-a very large number of groups is created when demand is high,
-but those groups will expire on schedule if a slump occurs.
-A stochastic method for triggering DKG
-would permit smoothing out demand fluctuations:
-Take the current number of active groups,
-divide by a threshold number of groups,
-and e.g. square root the result to get a(n insensitivity) number;
-Trigger DKG if the entry (interpreted as a number from 0 to 1)
-is less than 1 divided by the above number.
-If the number of active groups is below the threshold,
-this attempts to create a new signing group
-every time sufficient funding is present;
-with higher demand the number of groups
-tends to be proportional to _(number of entries in expiration period)^2/3^_.
-]
-
-==== Rewards
-
-A _base reward_ for each member of a signing group that produces an entry
-is specified in the system constants in the service contract.
-The nominal _profit margin_ of each entry
-equals the _base reward_ multiplied by the applicable _group size_.
-
-The exact rewards paid out to operators are based on the base reward
-but vary according to _submission delay_ and submitter position.
-
-If the amount paid out to the signing group in _group rewards_
-and the submitter's _extra reward_ is less than the _profit margin_,
-the difference is added to the beacon's _request subsidy pool_
-to incentivize customers to request entries.
-
-===== Group reward
-
-The group reward is paid to every member of the signing group,
-including the submitter,
-upon submission of a valid entry.
-
-The group reward equals the _base reward_
-multiplied by a _delay factor_
-equaling the fraction of time left by the submission deadline, squared:
-_group reward = base reward * delay factor_;
-_delay factor = (T~remaining~ / (T~deadline~ - T~begin~))^2^_;
-_T~remaining~ = T~deadline~ - T~received~_.
-
-The delay factor is counted
-from 1 in the first block a submission could be published in,
-to 0 in the deadline block which doesn't accept any more submissions.
-
-For example, assume the maximum time to submit is 20 blocks,
-the off-chain entry generation protocol takes 5 blocks
-and a request is made on block 1000.
-
-Block 1005 is the earliest block the submission could be published in:
-if published in this block the delay factor is 1.
-Block 1025 is the deadline block:
-no submissions are accepted and the delay factor is 0.
-
-If the entry is submitted in block 1009,
-the delay factor is:
-```
-((1025 - 1009) / (1025 - 1005))^2 = 0.8^2 = 0.64
-```
-Thus the _group reward = base reward * 0.64_,
-with the difference being the _delay penalty = base reward * (1 - 0.64)_.
-
-If the submission deadline is reached and the delay factor reaches 0,
-the entry submission fails and all group members are penalized.
-
-===== Submitter reward
-
-In addition to the _group reward_,
-the submitter is reimbursed for gas fees
-and receives an extra reward.
-
-The _submitter reward_ consists of
-the _callback expenditure_ to cover the exact cost of the callback;
-the _entry verification fee_ to cover the cost of verifying the submission;
-and 5% of the _delay penalties_ of the entire group.
-
-Unlike the _callback allowance_,
-the entire _entry verification fee_ is paid to the submitter
-regardless of their gas expenditure.
-The submitter is free to spend less or more,
-keeping the surplus or paying the difference.
-This is to incentivize optimizing gas fees.
-
-To incentivize a race for the submitter position,
-the submitter receives _delay penalty * group size * 0.05_ as an extra reward.
-With realistic group sizes this is significant,
-but not high enough to render certain attacks profitable.
-If the group size is 100 and the delay factor is 0.64,
-the submitter receives an extra reward of
-_base reward * 0.36 * 100 * 0.05 = base reward * 1.8_.
-In this scenario the full submitter reward would be
-_base reward * (1.8 + 0.64) + callback expenditure + entry verification fee_.
-
-==== DKG submitter reimbursement
-
-Getting to participate in a formed group is already valuable so there is no
-additional reward for a DKG result submitter. The only thing necessary is a gas
-cost reimbursement for the submitter.
-
-After DKG result is submitted, the amount of gas spent on the call is
-multiplied with the lower of the estimated gas price at the time of submitting
-the result, or the actual gas price of the transaction to get the _DKG result
-submission expenditure_.
-
-The entire DKG result submission expenditure is returned to the submitter
-from the _DKG fee pool_ of the operator contract.
-
-Any surplus between the _DKG fee pool_ of the operator contract and
-the actual cost of DKG result submission is returned back to the service
-contract. In the case when the entire DKG fails, the unspent fee will be
-transferred back to the service contract upon the next DKG triggered by the
-service contract.
-
-The minimum of the gas price protects the beacon against malicious
-miner-submitters. If the submitter is also a miner, they can place any
-arbitrary gas price on the transaction. Without taking the minimum,
-miner-submitter would be able to steal from _DKG fee pool_ of the operator
-contract.
-
-The on-chain DKG result submission code needs to have all deterministic
-and time-bounded run paths that are independent of miner-controlled inputs.
-If the miner-submitter pays the gas price estimated by the price feed, but
-tricks the contract into consuming twice the gas as normal, they will be able
-to get twice the reimbursement as well.
-
-==== Cost estimates
-
-===== Gas price feed
-
-A short-term gas price feed is required
-to estimate the gas cost components.
-
-The critical feature of the gas price feed is
-that the feed price multiplied by a safety margin for fluctuations (e.g. 1.5)
-should be sufficient for getting beacon entries processed
-within the deadline under all circumstances.
-The gas price estimate for an entry is set when the request is processed,
-but the entry submission transaction will be sent later.
-
-If actual gas prices rise to a level
-where the feed price and margin are insufficient
-for getting a transaction to be mined,
-and stays there for the duration of the entry submission window,
-the basic profit margin for the operators cannot be guaranteed.
-
-However, this does not imply that high gas prices
-would render the beacon inoperable.
-The submitter's extra reward incentivizes submitting
-even when the entry verification fee cannot cover the gas costs.
-In the extreme,
-avoiding the severe penalty for failure to produce an entry
-should incentivize group members to pay the gas prices
-up to the (theoretical) limit
-where gas for the entry submission transaction
-costs as much as the KEEP tokens at stake.
-
-The exact implementation of this gas price feed
-is out for scope for this RFC.footnote:[A rather obvious candidate
-is to use the gas price paid by the requester.
-This doesn't work if the requester is a miner
-as they can provide an arbitrarily low price.
-]
-
-===== DKG cost estimate
-
-The gas required for DKG should be calculated.
-DKG gas cost should include only DKG result submission. Ticket submission
-costs are covered by the expected return from getting into a signing group.
-Multiply DKG gas by gas estimate to get DKG cost estimate.
-Use a DKG frequency divider _d_ to set the group creation rate;
-once every _d_ entries on average.
-Divide DKG cost estimate by _d_ to get DKG contribution for each entry.
-
-The maximum DKG gas cost should be hardcoded in the operator contract.
-The service contract takes the highest applicable gas cost from all operator
-contracts being used and multiplies it by the fluctuation margin times gas price
-feed's estimate.
-
-Because DKG is performed when sufficient gas money has accumulated,
-fluctuations in gas prices don't need special consideration.
-When gas costs are rising,
-DKG gets performed less frequently
-until prices (and thus gas cost contributions) stabilize.
-As long as the fluctuation safety factor is sufficient
-to cover the immediate rise in gas fees during DKG execution
-the beacon is capable of generating new groups.
-Similarly, when gas costs fall DKG gets triggered faster.
-
-===== Entry verification fee
-
-Calculate gas required for verifying entry and associated support operations.
-The maximum entry verification gas cost should be hardcoded in the operator
-contract. The service contract takes the highest applicable gas cost from all
-operator contracts being used and multiplies it by the fluctuation margin
-(e.g. 1.5) times gas price feed's estimate to get entry verification fee.
-
-==== Cleanup gas efficiency
-
-As the gas cost of storing data in a previously zero field
-and later zeroing it again (20,000 + 5,000 - 15,000 = 10,000)
-exceeds the cost of modifying a nonzero field (5,000),
-cleaning unnecessary fields would appear to increase operating costs
-with little upside.
-
-However, gas costs in the entry submission transaction
-contribute 1.5 times as much to the effective price of beacon entries.
-Thus the 10,000 gas net refund per field
-is effectively worth 15,000 gas,
-making both options equal to the requester.
-The difference of 5,000 actual gas is effectively paid by the submitter
-in the form of a lower _entry verification fee_.
-
-Packing request data more densely,
-where applicable,
-could further reduce operating costs.
-
-===== Zeroing everything
-
-Resetting all request fields to zero after serving a request
-increases the immediate gas cost of making a request,
-but reduces the entry verification fee by a roughly equal amount.
-
-This results in a slightly lower total revenue for operators,
-but reduces the possible space of programming errors marginally;
-false positives for pending requests are eliminated
-even if the wrong field is queried.
-In practice this benefit is negligible.
-
-===== Wiping the minimum necessary
-
-Wiping only the necessary fields results in higher operator revenue
-for the same net price paid by requesters.
-Additionally, if a field remains nonzero but unchanged between requests
-even greater gas savings can be obtained.
-
-The field used to determine the presence of a pending request must be wiped.
-
-The requester address,
-assigned signing group,
-submission delay base time,
-gas price estimate
-and request fee
-are always written when a request is received.
-These are not necessary to wipe,
-but one of them must be chosen to signify the presence of a pending request
-with a nonzero value.
-
-Requester address, signing group, gas price and fee
-can theoretically stay unchanged between requests.
-If a single heavy user makes a number of consecutive requests
-with the same callback (gas amount) and gas prices are stable,
-this would provide a minor reduction in beacon operating costs.
-
-The submission delay base time
-is guaranteed to change when a new request is made,
-and thus is the most efficient indicator of a pending request.
-Using the maximum value instead of zero for "no request"
-is slightly more efficient.
-
-The presence of a callback can be determined by either
-the callback address or callback gas.
-
-The callback address is likely to remain the same
-only if the requester is the same.
-
-Because excess callback gas is refunded
-the only cost of setting a higher callback gas is the tied-up liquidity,
-with the exception of callbacks
-where excessive gas consumption indicates an error state
-where reverting is preferable to continuing.
-With well-programmed callback contracts,
-the callback gas amount is only necessary to modify
-if it needs to be increased,
-or if the requester cannot afford the higher gas allowance.
-
-This suggests that using callback address to denote the presence of a callback
-allows minor efficiency gains.
-Modifying the callback address when a request is processed,
-including setting it to zero in a no-callback request,
-further improves gas efficiency.
-
-=== Limitations
-
-Entry pricing is mostly static;
-entry quality has a slight effect on price
-(faster entries -> lower surplus -> lower request subsidies)
-but other factors apart from gas fees do not impact the price.
-
-Processing entries one-by-one doesn't scale.
-
-== Future Work
-
-Instead of rejecting new requests when one has already been made,
-the beacon could accept a single queued request,
-to be served after the active one.
-Other requesters could outbid the current queued request
-by paying enough to process the request and refund the previous one,
-and provide some specified (e.g. 1.2) increase in the profit margin.
-When the current active request is served,
-the queued request automatically becomes the next active request.
-
-This method would act as both a price floor and a supply cap,
-while capturing the effective price increase when demand exceeds supply,
-instead of letting it go to miners
-as customers try to get their requests processed first.
-
-== Open Questions
-
-The implementation of the gas price feed is out of scope.
-The method of estimating gas fees,
-the timespan over which the estimate should be calculated,
-and the fluctuation safety margin are not yet defined.
-
-////
-[bibliography]
-== Related Links
-
-- Flowdock Links
-////
diff --git a/docs-v1/rfc/rfc-17-undelegation.adoc b/docs-v1/rfc/rfc-17-undelegation.adoc
deleted file mode 100644
index 7c3708a42f..0000000000
--- a/docs-v1/rfc/rfc-17-undelegation.adoc
+++ /dev/null
@@ -1,383 +0,0 @@
-:toc: macro
-
-= RFC 17: Stake delegation and undelegation
-
-:icons: font
-:numbered:
-toc::[]
-
-== Background
-
-Token owners delegate staked tokens to operators.
-Owners need a way to cease staking at their discretion,
-subject to the controls necessary
-for the intended functioning of the Keep network.
-
-== Proposal
-
-Undelegation can be initiated by either the operator,
-or the owner of the tokens delegated to the operator.
-After a defined waiting period is over,
-the owner can recover the previously delegated tokens.
-
-=== Goal
-
-Delegation and undelegation should be
-conceptually simple and easy to understand.
-Operator contracts should be able to determine
-an operator's eligibility for work selection
-inexpensively and safely.
-
-=== Implementation
-
-The staking contract records two time (blockheight) fields for each operator:
-the block the operator was created,
-and the block undelegating began.
-
-Operators can be:
-
-- _non-existent_
-- _not ready_ for work selection because they were created too recently
-- _active_ and eligible for work selection
-- _winding down_ and ineligible for work selection but finishing earlier work
-- _finished_ undelegation so the owner can recover their tokens
-
-Using the systemwide constant _undelegation period_,
-the operator's _status_ can be determined
-from the creation and undelegation blocks.
-
-Operators are uniquely identified by their address
-and operator addresses cannot be reused,
-even after returning the tokens to the owner.
-
-To reduce the impact of transaction reordering,
-both delegating and undelegating take effect on the next block
-after the block the transaction is processed in.
-
-==== Parameters
-
-===== Operator initialization period
-
-E.g. 50,000 (roughly 6 days)
-
-To avoid certain attacks on work selection,
-recently created operators must wait for a specific period of time
-before being eligible for work selection.
-This waiting period must be greater than the highest permissible time
-between the making of a beacon entry request
-and the request being served.
-In the ideal case, multiple entries would be requested and generated
-within the initialization period.
-
-If the initialization period is insufficiently long,
-the pseudorandom work selection process can be subverted
-by creating operators whose identifiers (addresses)
-are calculated to yield advantageous outputs in the selection function.
-This can let the adversary control the majority in the new signing group.
-
-If the new group is in line to sign the next entry,
-the adversary could choose the group's private key
-so that the following entry also gets signed
-by a group controlled by the same adversary.
-With sufficient calculation capability,
-this can be repeated _n_ times at the cost of roughly _O(k^n^)_ calculations
-where _k_ equals the number of active groups
-divided by the number of active adversary-controlled groups.
-If another signing group is created within this time,
-it can be similarly controlled.
-This can eventually lead to the adversary controlling the entire network.
-
-With the initialization period,
-the adversary has to create the operators in advance
-long before they become eligible for work selection.
-Thus the adversary has to be able to predict each entry
-generated during the initialization period.
-With an unreasonably powerful adversary
-that can arbitrarily frontrun 50% of all entries,
-generating _n_ entries within the initialization period
-provides _2^n^_ security against this attack.
-
-===== Undelegation period
-
-E.g. 800,000 (roughly 3 months)
-
-The staking contract guarantees that an undelegated operator's stakes
-will stay locked for a number of blocks after undelegation,
-and thus available as collateral for any work the operator is engaged in.
-
-==== Stored information
-
-----
-mapping(address => Operator) operators;
-
-struct Operator {
- uint128 stakedAmount;
- uint64 createdAt;
- uint64 undelegatedAt;
- address owner;
- address beneficiary;
- address authorizer;
-}
-----
-
-Each operator stores the addresses of its owner, beneficiary and authorizer,
-the amount of tokens delegated to the operator,
-the block it was created at,
-and the block it was undelegated at if applicable.
-
-Ethereum produces a block roughly every 10 seconds,
-or around 3 million blocks a year (~2^22^).
-Thus, `uint64` should be more than sufficient for blockheights.
-With 18 decimals (2^60^) and 1 billion tokens in circulation (2^30^),
-any applicable amount of KEEP tokens can be stored safely in a `uint128`.
-The staked amount and creation/undelegation blocks
-can thus be packed in a single storage field.
-This makes it slightly cheaper for operator contracts
-to determine the operator's eligibility for work selection.
-
-The exact types are a recommendation,
-and the implementation is free to use larger unsigned integers
-if it yields favorable performance outcomes.
-
-==== Operator status
-
-----
-enum Status { NonExistent, NotReady, Active, WindingDown, Finished }
-
-operatorStatus(address operator) -> Status
-----
-
-An operator's status determines what actions are available
-for the operator and the owner the delegated tokens.
-
-===== Non-existent
-
-The operator doesn't exist.
-
-`operators[operator] == nil`
-
-===== Not ready
-
-The operator has been created in the same block the query was performed in.
-The operator is ineligible for work selection.
-
-An operator is `NotReady`
-if the current block is equal or less than
-the creation block plus the initialization period.
-
-`block.number =< operator.createdAt + initializationPeriod`
-
-===== Active
-
-The owner has delegated staked tokens to the operator,
-and the operator is eligible for work selection.
-
-An operator is `Active`
-if the current block is greater than
-the creation block plus initialization period,
-and the undelegation block is either 0 or equal or greater than the current block.
-
-`block.number > operator.createdAt + initializationPeriod && (block.number =< operator.undelegatedAt || operator.undelegatedAt == 0)`
-
-===== Winding down
-
-The operator has been undelegated and is not eligible for work selection,
-and the operator is finishing any work they were selected for earlier.
-The operator's backing tokens continue to be locked as collateral.
-
-An operator is `WindingDown`
-if the current block is greater than the undelegation block,
-but at most the undelegation block plus the undelegation period.
-
-`operator.undelegatedAt < block.number =< (operator.undelegatedAt + undelegationPeriod)`
-
-===== Finished
-
-Undelegating the operator has finished.
-The backing tokens are unlocked and can be returned to the owner.
-
-An operator is `Finished` if the current block is greater than
-the undelegation block plus the undelegation period.
-
-`block.number > operator.undelegatedAt + undelegationPeriod`
-
-==== Work selection eligibility
-
-`eligibleStake(address operator, uint block) -> uint`
-
-Operators are eligible for work selection
-based on their status in the block the work selection started in.
-In some situations an operator's status may have changed
-after work selection started,
-but before the operator contract queries it.
-For these cases the staking contract must provide a way to determine
-the operator's eligibility for work selection that started in an earlier block.
-
-It is the responsibility of each operator contract
-to query operator eligibility with the correct block number.
-Failure to use the correct block leads to minor manipulation opportunities.
-For example, querying an operator's eligibility
-on the current block when they submit a ticket
-means that an ineligible operator whose initialization period is almost over
-could wait to submit their ticket
-until they become eligible for work selection.
-
-To make determining an operator's eligibility for work selection
-simpler and cheaper,
-the staking contract must provide the `eligibleStake()` function
-which returns the number of KEEP tokens available for use as collateral.
-
-When calling `eligibleStake()`,
-the staking contract assumes `msg.sender` is an operator contract.
-`eligibleStake()` does not return meaningful results
-when called by an address that doesn't correspond to an operator contract.
-If the `operator` is ineligible for work selection on `msg.sender`,
-`eligibleStake()` returns `0`.
-Otherwise `eligibleStake()` returns `operator.stakedAmount`.
-
-----
-operatorExists = operators[operator] != nil
-
-senderAuthorized = authorized[operator.authorizer][msg.sender] == True
-
-operatorReady = block > operator.createdAt + initializationPeriod
-
-notUndelegated = block =< operator.undelegatedAt || operator.undelegatedAt == 0
-
-if operatorExists && senderAuthorized && operatorReady && notUndelegated:
- return operator.stakedAmount
-else:
- return 0
-----
-
-==== Actions
-
-===== Staking
-
-`stake(uint amount, address operator, address beneficiary, address authorizer)`
-
-Staking tokens delegates them to the operator,
-who can then use them as collateral for performing work.
-Staking is performed by the owner of the tokens,
-who must have authorized the staking contract
-to transfer `amount` KEEP to itself
-(e.g. via `approveAndCall()`).
-
-`token.allowance(msg.sender, stakingContract) >= amount`
-
-The nominated operator must not already exist.
-
-`operators[operator] == nil`
-
-The staking contract transfers `amount` KEEP from `msg.sender` to itself,
-and creates a stake delegation relationship,
-with the operator becoming `Active` in the next block.
-
-----
-operators[operator] = Operator {
- stakedAmount = amount;
- createdAt = block.number;
- undelegatedAt = 0;
- owner = msg.sender;
- beneficiary = beneficiary;
- authorizer = authorizer;
-}
-----
-
-===== Cancelling staking
-
-`cancelStake(address operator)`
-
-The owner can cancel staking within the operator initialization period
-without being subjected to the token lockup for the undelegation period.
-This can be used to undo mistaken delegation to the wrong operator address.
-
-`msg.sender == operator.owner`
-
-`block.number =< operator.createdAt + initializationPeriod`
-
-If staking is cancelled,
-the staked tokens are immediately returned to the owner,
-and the undelegation time is set to the present.
-
-`operator.stakedAmount = 0`
-
-`operator.undelegatedAt = block.number`
-
-===== Undelegating
-
-`undelegate(address operator)`
-
-Undelegating sets the operator to `WindingDown` status
-so that the backing tokens can later be recovered by the owner.
-Undelegating can be performed by either the owner or the operator.
-
-`msg.sender == (operator || operator.owner)`
-
-Undelegating can only be performed on a currently active operator.
-
-`operatorStatus(operator) == Active`
-
-The staking contract sets the undelegation block of the operator
-to equal the current block,
-making the operator ineligible for any work selection in the future.
-Work selection performed earlier in the same block shall proceed as normal.
-
-`operator.undelegatedAt = block.number`
-
-===== Recovering tokens
-
-`recoverStake(address operator) -> uint`
-
-Recovering staked tokens transfers them back to the owner.
-Recovering tokens can only be performed by the owner,
-when the operator is finished undelegating.
-
-`msg.sender == operator.owner`
-
-`operatorStatus(operator) == Finished`
-
-The staking contract sets the staked amount of the operator to zero,
-and transfers the previously delegated tokens (or however much was remaining)
-back to the owner.
-
-`operator.stakedAmount = 0`
-
-The staking contract may additionally clean up
-the owner, beneficiary and authorizer addresses for the gas refund.
-However, the staking contract must not delete
-the creation and undelegation times,
-as this would enable reuse of the same operator address.
-
-=== Limitations
-
-The amount of tokens delegated to an operator cannot be changed afterwards.
-
-== Future Work
-
-The definition of `Active` operators
-permits setting `undelegatedAt` to an arbitrary date in the future.
-This can be used to e.g. delegate stake to an operator in a time-limited way.
-
-There is no obvious reason why undelegation couldn't be cancelled by the owner.
-
-The authorization queries by `eligibleStake()` can be cached to save some gas.
-
-== Open Questions
-
-The operator initialization period provides an appreciable level of security
-against work selection manipulation.
-Whether other mitigations are worth implementing
-has not been thoroughly examined.
-
-////
-[bibliography]
-== Related Links
-
-- Flowdock Links
-- Other links
-- If you have publications, you can include them in bibliography style. If you
- start your bullet with an id in _triple_ square brackets (e.g. `+[[[AAKE]]]+`),
- you can reference it in the content body using regular cross-reference syntax
- (e.g. `+<>+`).
-////
diff --git a/docs-v1/rfc/rfc-18-files/release-flow-chart.png b/docs-v1/rfc/rfc-18-files/release-flow-chart.png
deleted file mode 100644
index b0e91fcc452635afc7364f85b4e2a007733bbccd..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 348256
zcmeEv2{@Gd-@b}=B$dimDOyBj%QjO{k{G3;Y?Y9R?At7*MG}%C>nK7glI&X&vW|W1
zQ?|j_$IO`h{~bE#bWZ1-miL_Z_xoSh+jYq-&ph)y-{rI1pZoss)7R7DUAlfL7Z(?=
z_F>KATwF_ixVX5Hix+}dSm_yyxww{F*=T6!Yinq1(06jMvaz$|;yUd2&~TASh?a1X
z`-S_j<_p{tAg?@V#kFqZ3$FQlc#bX6-f-^yqZKDiZm(JW!dUali8tHN*I(j^=hJ+V
zzSW+vmG8v%45QMUmF^qoy+rm>)QfNh6pS;5i4M-AbT8PK7$O_e|2UVcPiI-*B~)-z%X}RrS>`@l}hM&qq2Q1=V!uCLPLBtvmU`oV^YvkK7A
zm@WMN*w(74)f&|EPtPxrJ#>A?viE)h!?d$`JdEO*fDQI5w3W3r)HapAAAD?bB8uKF9)1Zh<*?OECE
z*t1TV@nNs4n#ac53r$wcH`=$vSn|pS=iD`>i$AfOngWS7rw_(1_`kK1C4~hl0
z!6mP5nvl}m6uUM?NNw--`8W01=Zun(xmRBl*S{-Xm-A8JJ$1v5j8i>o4(k(l41qZ`wxNW)Zw=)^1%1(?%$cCLJ%detF-@bi|LAx9?wBitog=oo9txd5~Q6{SteZ2VOUSt9(VkgeU7GZD>AhzpMujO@MpjMwc7c)=I3o
zy|d?T_C~wSTuTl<3HI2$x?JfX-v4tpzcbn^v4s})C%~jr
zRbL*$YrX!Iu-NXA3+IojN(P0On-q6q^2^{#@9em(Z(MxeAV89k3Glcq->~(=;R`3M
z-e3ox*Q;8DIwm=$Om6Qz)T=6)?H5wP9kNa`Qdcix`mX%iA*JKHUfcDtf{VhRB7$Qwj;cyi4_5i$$$G{~pY4b6aFneuvLFfwLRajBFjNd-y{)`j=E%
zoP6DGR1lgFDiC_4>SgF?DDxEgl=i7Dr@UW|85z86YdPIw`_lNO_ho6jvX1JsXX(_M
z(DPN9t2XnwK6SIdL_&K
z^^!soLt3A;5BbOqkMv7BcK3DezO$>+`hm-dnk0gZyilOdW1Z-#g8J(E`Z%3KN`Xkl
zGOMHQk4{?X1yBcvha&K~U8EKxW?Ha?PMKm5v!kX$_v5Kix6lCKpn{p>o9_F;
zBE6g!b_?%;DUEp*`kQUe_&Lkebfh>NsLK(g@*3pG8w4zKCv`7j@0d
z7=>AdDV4=KWZ^;_$-SDrnL*wk9r`g8+%Rt4+oc~C&&b5e)$O?_ZY1ad{h)Gq?Hh@~
z-Q~d{C2b|1Yev>f^F!7$A_!H{RhO3(A9$xxd7xc`q!Dr;`M~(C(>E=Bn{SeCdEdhD
zIrweR)I9j&PIj$a?-GxU{O-f!A98{(AA6H@Bk6e(y3UQ2t3*xUWxYFaQ$BJ{WR5Hb!e!0$#_+trG53t>MJ}19@x$O?=s%m2Nzw;
z7<3FpwG6+IYGbw8zRoMX*0a5LWSYM
zYQ1ld7KAs1rqt~xIgWI0;9ON%t!cIszk$1w(3z3HF*{L(J<^GmYovtu@
zBU;)~Be%@XjQl4I=APo$>9{~<=2XYE{?k<*h8{0l^Y3RL&z)+2{`O?vDZ)#cGt9F!
zGYY)6r){fR3Qd$;yTX?S-PuWaMtDe2-4VAVQnA&}DCZO6VfOGP*DIv%fCS+%dw79%
z_E5t>Yz@h{I`e^pCndTsPuRF5OR=f7`GlQ>{fsLIC!~lbVGD>
zUXOc5vlq5yOtGur3ExYD7T0lYob#mbJ@JTP)8VW!%dwrfMdWQ1=A=bg5SFYp>Y)A>
zqR$Q)g$eWT;R{vRz?;6_OSm*3TKAc*sP88J3`M$vIKy)qqsnhAmI68NaiR3saQ#88
zMS-hD3AVu*(;^rME7tWA;iaG;%)}5PkX~OWY|tO-TOP6A0>-o@27NS
z#~=%cw{Bzw?3Xg@1VltTRSrjE_(_Qyve^jj4ABc$6zY4K+roc
zrV7o^C>Xgp=^rhtZk99_l6<3w
zoufPEzlF4p_-t_B&Gj5cdcWanZXUlwP9=#j$*RAz9w~*`Ex~u$C*RHX2
z7c3C}D7rdt$-XKVlBvNKO%J6RnZq|z)-Uld7J5?Xiwx}zQ`bNEabDpFn@2v(uVvSE
zmLo_!?pPXWTj}a@Z3mARb8*jG&&2~C%>zG>dBVRwJ~VGD*MiyC=W}uS+Hi4yK1L7x
z=KQ+{emI|*`@P`)Ev`l2*-G%^5j+2vqnG-`F8Jj!Hxj(ZwckKPTO0f~uyC@pw0FMf
z;BwoGeg?d-J_0nXoQbHd2QNcX6Ug~Mf;a~B-WTgrG`zQQ>V
zmzswPczD^;<=h63%Xaq8Djw>aW{*$-k2x>PZrU(=h>NZICL>+_4H^zkmKzjgXR$Mc>B5(#}ZJ<}w&F@EwpnipsmxWcNX
zSHVa_ma57AI%|-ngU3so!9{>_Ji|F+Kk29M|WoqwxE0q^hQ($?I6
z!eib@*X6qxu&2rNE(<9+Ke8}fxO3yi
z)x{f&7n#l9w0G&f6$dv!-p^aI|Ayw`4I6zl-+Py>E%oCGzPCbr@yhqI6=wy#)hxW#
zG85_5DKUA^TiV^3wwNY2gS=t$<3`>ulfB)W9n71@o}F$MG+_atSqkZl2y~
z5JdXzGiJRn&)y6u?G;xd`6mwUgQ(hbi&|YL=nEg&dC9EFs99?B)G>7DmQ$o9e()wK
zcfXT}1DnK26{hD;qVIjsLO6x}XAW_4kr>=pG}IIjYne724#_yIj7^+QvZgg{>Ni0*
z#KjC5_&;z)90~GDfbBe9OWLOXpFIeEQe4R=SKy7^2?gVfvyQosYkLF7R@D6G#_zA^
zveMDo!NH-(q|zFXK|AP0?G5(DzM{Qdz%QSLL(&!Chggp_y3nqwK@ch_@V{g=e04Wl
z%cFM`JxjwLs$(*lR@T;uj1j^kb=FL8O^p%`E{Z;ltkkDich$zhJfjK!^~-0GGh03%
zwI1S7*4+G<6;Id4Pa4vD`Y%oY&o=uv%*d2WoRUvw(P%o;+}jovX+sv)^=*&c+vEw~
zgg+SYFU)*-+RVu4sIK_iUa}h*)|vuDzBrRA?PT;O
z1+yvqx+~(FrWY;LVhsi|M%CRuSHQ*H9UBna`BYwXcnKKE&aIJV2}4gH26v|Sp&wZ0
zCSe|IQm>P;43`;}dwQ6ETKjZ@KkewYh6RY@p+A1u-Zf}4vTSsEsL?U|$}|aoQ$A$h
z_jwJMW>&Vqbfv@c%SwJJUdE&Y@3G=l%N!k1^g!CH2j4d#U%H}>7GVCwrq3l2AYl2h
zeb9;DF$+0C!uz`xM=13U59`aW;B^&4fAGjz|Lp<)<1LmqaE74^
z<*qSlYDJgIEu9fYhyQr|?;NS@i`lEV!z(;HVepMSvSGse!?nZ_p^LAKQ2zF_U#wfZ
zTQG0Y-ho5eAqPJ9naH!!OCw|g5Epq1g6Zu(-V8*p>SPc?9>6B9+>^WU;
z?Z;J)WPhh=z*x<^!S1%V=XRC2=<-<1*9&(pi8#YdEIja&e$;7~yF`-kexj9$spv4z
zJ>cjB*MT7u{l6jm%lPEKc*uwW-HY2WZDf)$Z$yB`{$62!9lb>nY8Dy!+mj(9GxFNB(M};yhuC>a<#)g@3L3^
z;9D$Ss6ylg;rn9Uly)?@Xs@A$r_Z|UpZ}NTm8!W489{j!u`^ikEZ>YAr
zyBjI?F!^(wdQ8TweB|09v5WRaOfq4nddlEdE|lOVhNvW%V5XlPtjvKt)lzRvT(b>N
zdmu(Siarw`MKJJcl0#eyc1nQ_9s5rnr2J^ygsK}*py)F;KCYyys!Bbba*i}vF79Ao
zNFA`9xy#V-ox7VUg6KcE*Z!Fu`}r)#0$Da5YF8r)9pX@13;JM^b
z9w=(77o*lzZ?bxq9tfYyrVf~>jTOd0q@Vuqd<|ui@FQ*M2KNjS^>l-TMC~Fmn|u!v
zXwvtUjlKhB@jQo6^pY6NamFVI?+55!*WyakBaM$^u4+V=2fQA#jQB?)_&>`BEGBKn
ztvmJ55K-S{TIMLT!*WZ$)14WPf><_{QC8;`GWa~}q^u^KnU=poh>|s)#IG~-!^S%I
zGSg9FaKHGi+%a&|6xkWi=ii=%5PG%%0BtvuOSx&DV2yo)rGGYpJ?
zSk@;0!2{}iq{0$?{JJV)vYUw_*7xS$4hiucZT2c!U(HRJ(D4bU9DxV_7d!tYUiN?K
z#t%b`|HVUw13~F1sA!_0P|x_hyu2DeK`E7`8q5W#B%)DM?UwCprnl`?5k#nLF7<)%
zXjwmj`NkX7C4L+{Iz4o6)iT;Dk!U}N=>7Bi(LQl<^@$qCr3VeJxJc4m4&UKHEDfyH
zMDuB<#lni~!v`BTZu`T@_N+lK5{F;$!a3xPW)4k0SzwMf-|YM<<=eJ{W1(^{p*VK;
zsZLmemsXHiv=~PG#nQF-^}}iwo*QMv+;PXmLmPhFnsm?_@fl3dw9CYB)CeMwbZ*PH
zafZ*p&YrIQDkq9TIxoDR`uxYO=nsPTPUz@@f&!-6cEb*6S`5>MG!++$5%c(XZGhb2
zV9vUx138~WPq)X{`^x73I8O6pB?Bo+Th3IZwD;xNsKU+7Z7SWQWVkm7+T95!)?g>r
zQGGvGF8Z*l|7`_?Um)WrBFx4Km|FeF*jVUx>~12gL@wgr9ypK}I&wggv~wEj^L$k>
zcu?#a05F{gnttOmwhkwez7xUuzJ2q%WmbXcTs(ZJE`Ob&Vb|bowSa&5ehCe;#gA2y
zxiSX>REGk`{*#5HU*`SmB35NRCxhK7e5|H(@tOZvKJuM861J2BDsythQFf18--qD6
zQGo=fjXiuh7Rvuh#jbf4oG&%Ce~l$2ermq{*bFc34`a@R)sW6@{BC1umhX{fv#hB*
zP*k-gO3m|iobs&cl$CdtIrf(x;~#K8A!##F>fUZ%I9Rlbg1VW@M*`9R0$mf!uxY{Y;rFZ_r%Xu7EYA?RAoU7m7C=&9+P7U-q{i_Ya0PNH+dszmvpP;$R$R<-9;9>pOEE
zbj^fKszv9l(fl>nn54rHH-8dS>N`938|biX14y5w_L#{isq6`Y(4+-EwvK;q0l#fI
znygY*!!cX|zmzt_ir7ttNk0i~@eTY2O%!nL;S~FN`<>z>{%^?s5;FWR9B5^Y9sF|WbLL#9Qf7URU9Ddl>ysCWuhMcpL$OEo2wN#
z!=OwTVl<8#U4vrbQHm&%AxeSzGPZF-g^!QuNXqfn=n}^*K70AwVc@Uh*7xj-;{IEJ
zK^N73`Vm6Q=80}fVU{N)57)(LLo-hkYjBL35PlB4jihIx@~D338NUIUFlW;SYE{SWkYsCAW)85fkuc;`NDXJo6#1cyE5t44Q(I~#
zd&?uyY%1Epj5QSoyNdQ42p{jg3dp$MPJec5@&fTXTB*KwcpsFCwgP`l&4?w?#iy
z!`>S;(*_C=h|nch#)vxKLpJ2>kGW;%nk01A7qA)zC!DD4v|2UVV7lg2iz4>7D-*iJ
zAs8x`+Ty@$8Sq68`bJRl@#-NsZW?D4YRaLk$$^8iUdI|)l6B+E?(xe2{O*D`isIzw
zA#kaMsh%am-MiXE+F1jbAb6idjcWH~;DClWO`q6r&g!qxg3{^-O2k=Lh^j?I)sULl
zxtUFaLW+KXLHURMWj%^?_Q4I#c>Qhs`I`}FM=wD0BPXucz?e-i1=PeMR2>{gLEtWE
z;5%?Eas@k%Aj@o!RR~g>`fwo~udCE0PrZSG56FcC#G)AGs7`pfJ6wwxfz40wY>ez~
zVob@horw3t^5fgu+H8i(rO@mngwY+6z(?nh5vE<#?eVV26g#?WSk>atTa>
zBcm@7kBJ|GC2k&|_w-PScqx?Gv&AVEARrWjPZSSig3^4TxBfrRqRVQ-x7J(K)C0G^
zVRT^~n-RpeD;#FCo>w>!?XHt=j%5{+UWU{}jeBA962v>i^80r>gfkNA^2TzLsmi?Q0Z-mu4*rlV@
z;c_)fh(;v^^vrvy2-UG{i`Sj@+{}nnYD5LQm%cNrbEUY7C~8Uy0aeGb2I^erh5~`qO}-~~w={87qmwq>#JX|nr<2)1=uw`{nJ?z`W&<8c;qCUqN3=VJ`96A$J8ap|2XqEXQdade
zUHB*gXOcVO{2D%oT}tJ(rz;?=*0cpf!Yl1`(cuT(;$aDUj2o@3f<=cyo>jL@ho8Qn
zMZ2*5dk*UuA=bJVI_LVOXPkZ`@P^5Yc7XQ^N8*@WxSfk-%?mp_uaxkHWKeryU6f}7
zg|IFx