Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC 12 Implementation: Coordination procedure #3745

Merged
merged 15 commits into from
Nov 30, 2023
Merged

Conversation

lukasz-zimnoch
Copy link
Member

@lukasz-zimnoch lukasz-zimnoch commented Nov 24, 2023

Refs: keep-network/tbtc-v2#737
Depends on: #3744

Here we present the second part of the changes meant to implement RFC 12: Decentralized wallet coordination in the tBTC wallet client. This pull request focuses on the coordination procedure.

On the code level, this is about implementing the coordinationExecutor.coordinate function.

Coordination seed

Calculation of the coordination seed was implemented in the coordinationExecutor.getSeed function. This function computes the seed for the given coordination window according to the RFC 12 specification:

coordination_seed = sha256(wallet_public_key_hash | safe_block_hash)

The computed value is used to initialize the RNG for random operations executed as part of the coordination procedure. Those operations are:

  • Leader selection
  • Heartbeat execution

Coordination leader

Leader selection was implemented in the coordinationExecutor.getLeader function. It uses the coordination seed to select the leader operator from all operators backing the coordinated wallet. The exact algorithm is:

  1. Get the list of unique operators
  2. Sort the list by address in the ascending order
  3. Randomly shuffle the list using an RNG initialized with the coordination seed
  4. Pick the first operator from the shuffled list

Actions checklist

The next step is determining which wallet actions should be checked and possibly proposed during the coordination window. A list of such actions is called actions checklist. Actions on the list are ordered by priority, in descending order.

For example, if the list is: [Redemption, DepositSweep, Heartbeat], the leader must start by checking if redemption can be proposed. If so, it should do it. Otherwise, it should check the deposit sweep. If neither redemption nor deposit sweep can be proposed, the leader should propose a heartbeat.

Actions checklist assembling was implemented in the coordinationExecutor.getActionsChecklist function. The exact checklist depends on the coordination window. The specific algorithm is:

  1. Check the possibility of redemption on every window
  2. Check the possibility of a deposit sweep, then moved funds sweep, then moving funds, every 16th window
  3. Draw a decision regarding the heartbeat proposal, with a 12.5% chance of success

Leader's routine

If the given operator finds itself to be a leader for the given coordination window, it executes the leader's routine implemented in the coordinationExecutor.executeLeaderRoutine function. It uses the actions checklist to generate a proposal and broadcasts the proposal to the followers, using the underlying broadcast channel. It completes the coordination procedure returning the generated proposal as a result.

Proposal generator

The leader uses the proposal generator function to generate a proposal based on the actions checklist for the given window. The generator is expected to return a proposal for the first action from the checklist that is valid for the given wallet's state. If none of the actions are valid, the generator returns a no-op proposal.

Implementation of the proposal generator is beyond the scope of this pull request and will be handled in a follow-up PR. The plan is to use the code from pkg/maintainer/wallet that is currently used by the wallet maintainer bot.

Follower's routine

If the given operator is not the leader for the given coordination window, it executes the follower's routine implemented in the coordinationExecutor.executeFollowerRoutine function. It listens for incoming coordination messages and accepts the first message that:

  • Is of the proper type
  • Is not a self-message
  • Comes from a sender with a confirmed wallet membership
  • Refers to the currently processed coordination window
  • Refers to the coordinated wallet
  • Comes from the coordination leader designated for the given window
  • Holds a proposal referring to an action from the checklist or a no-op proposal

The operator-follower completes the coordination procedure returning the received proposal as a result.

Next steps

The next steps on the way towards RFC 12 implementation are:

  • Implement proposal generation
  • Finalize coordination result processing (i.e. implement the processCoordinationResult function and refactor node's handlers appropriately)
  • Remove the existing chain-based mechanism (i.e. detach WalletCoordinator's events handlers and remove unnecessary code from chain.go)
  • Modify the SPV maintainter to not rely on WalletCoordinator's events during unproven transactions lookup

Here we implement the logic of designating the coordination leader according
to the specification presented in RFC 12.
Base automatically changed from rfc-12-impl to main November 27, 2023 13:22
Here we are implementing the code responsible for building an actions
checklist that will be used to generate a proposal. We are also adding
an outline of the leader's routine.
Here we implement the coordination message type along with all marshaling
machinery necessary to transfer it over the wire.
Proposal generation must have a way to identify the wallet. Code currently
used by the wallet maintainer (`pkg/maintainer/wallet`) uses 20-byte
wallet public key hashes for that purpose. As we plan to reuse it in the
new mechanism, we should use the same identifier.
Here we implement the follower's routine along with necessary message
validation.
@lukasz-zimnoch lukasz-zimnoch marked this pull request as ready for review November 29, 2023 14:27
@tomaszslabon tomaszslabon merged commit 4b78c97 into main Nov 30, 2023
29 checks passed
@tomaszslabon tomaszslabon deleted the rfc-12-impl-1 branch November 30, 2023 16:25
tomaszslabon added a commit that referenced this pull request Dec 4, 2023
Refs: keep-network/tbtc-v2#737
Depends on: #3745

Here we present the third part of the changes meant to implement [RFC
12: Decentralized wallet
coordination](https://github.com/keep-network/tbtc-v2/blob/main/docs/rfc/rfc-12.adoc)
in the tBTC wallet client. This pull request focuses on proposal
generation.

### Remove wallet coordination from the maintainer module

So far, the maintainer bot implemented in the `pkg/maintainer` package
was responsible for wallet coordination. The logic was living in the
`pkg/maintainer/wallet` sub-package. As the maintainer bot is no longer
responsible for wallet coordination, we are detaching the wallet
coordination from there. This has also an impact on the maintainer-cli.
Commands responsible for deposit sweep and redemption proposal
submission are no longer available.

### Move code from `pkg/maintainer/wallet` package to `pkg/tbtcpg`

Although the maintainer no longer uses the wallet coordination code,
that code is still useful for the new coordination mechanism. It
contains the logic necessary to produce coordination proposals. Hence,
we moved it to the new `pkg/tbtcpg` package and exposed an entry point
component `ProposalGenerator` that implements the
`tbtc.CoordinationProposalGenerator` interface. Thanks to that, the
`pkg/tbtc` package can use the code from `pkg/tbtcpg` to generate
coordination proposals.

Ideally, the code from `pkg/tbtcpg` should be embedded into `pkg/tbtc`.
However, both packages are not compatible out of the box. Merging them
would require a lot of breaking changes. As RFC 12 implementation is
already a complex task, we decided to keep `pkg/tbtcpg` as a separate
being for now, to reduce risk.

Last but not least, the code in `pkg/tbtcpg` was simplified. This code
no longer needs to handle proposals for multiple wallets at the same
time so focusing on a single wallet allowed us to remove redundant code
and facilitate further maintenance.

### Wire up `pkg/tbtcpg` package to `pkg/tbtc`

As mentioned in the previous section, the `pkg/tbtcpg` implements the
`tbtc.CoordinationProposalGenerator` interface so it can be used to
generate proposals within the new coordination mechanism. This was
achieved by injecting the `tbtcpg.ProposalGenerator` as a dependency to
`tbtc.node`, during the setup process.

### Next steps

The next steps on the way towards RFC 12 implementation are:

- Finalize coordination result processing (i.e. implement the
`processCoordinationResult` function and refactor `node`'s handlers
appropriately)
- Remove the existing chain-based mechanism (i.e. detach
`WalletCoordinator`'s events handlers and remove unnecessary code from
`chain.go`)
- Modify the SPV maintainter to not rely on `WalletCoordinator`'s events
during unproven transactions lookup
@lukasz-zimnoch lukasz-zimnoch added this to the v2.0.0 milestone Mar 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants