Here we present the first part of the changes meant to implement RFC 12: Decentralized wallet coordination in the tBTC wallet client. This pull request focuses on the groundwork necessary to run the off-chain coordination layer.
Coordination layer orchestration
The node orchestrates the coordination layer upon startup. Specifically, it runs two separate goroutines:
Coordination window watch
Coordination result processor
Both goroutines are steered by the node's root context and communicate through a dedicated channel.
Coordination window watch
The coordination window watch goroutine is responsible for detecting coordination windows that occur every 900 blocks. Once a window is detected, it runs the window handler function and passes the window data as an argument.
The window watch process guarantees that the window handler is called only once for the given coordination window. Moreover, it also guarantees that the window handler is called for all coordination windows. This is achieved by calling each handler in a separate goroutine so the watch loop does not block for long and the chance of missing a coordination window signal is negligible.
The window handler function triggers the window processing logic. Specific steps of that logic are:
Determine the list of wallets controlled by the given node
Take a coordination executor for each wallet
Use the coordination executors to run the coordination procedure for each wallet (in parallel)
Collect coordination results and push them to the processing channel
Coordination executor
The coordination executor is a component that is responsible for running the coordination procedure for the given wallet and coordination window. It is designed to encapsulate the logic of the procedure (coordination seed, communication, and so on). It also ensures that only one instance of the procedure is executed at a time. The executor is also responsible for assembling the coordination procedure's result and reporting all coordination faults detected during execution.
The design of the coordination executor is inspired by the existing signing and DKG executor. It attempts to fit the coordination procedure's logic into the existing codebase in an elegant way.
Coordination result processor
The coordination result processor goroutine listens for incoming coordination results and triggers the result handler function in a separate goroutine to ensure all results are processed independently.
The result handler function triggers the result processing logic. Specific steps of that logic are:
Record coordination faults reported in the result
Detect the type of the action proposal being part of the result
Fire the appropriate proposal handler
The proposal handlers are part of the existing codebase. They are responsible for the orchestration and execution of the proposed wallet actions.
Intersection with the existing chain-based coordination mechanism
The presented groundwork was built alongside the existing chain-based coordination mechanism. Some initial integration steps around data types were done. The existing mechanism will be gradually removed and replaced in the follow-up pull requests.
Next steps
The next steps (coarse-grained) on the way towards RFC 12 implementation are:
Implement coordination procedure logic (i.e. implement the coordinationExecutor.coordinate method)
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
Refs: https://github.com/keep-network/tbtc-v2/issues/737
Here we present the first part of the changes meant to implement RFC 12: Decentralized wallet coordination in the tBTC wallet client. This pull request focuses on the groundwork necessary to run the off-chain coordination layer.
Coordination layer orchestration
The node orchestrates the coordination layer upon startup. Specifically, it runs two separate goroutines:
Both goroutines are steered by the node's root context and communicate through a dedicated channel.
Coordination window watch
The coordination window watch goroutine is responsible for detecting coordination windows that occur every
900
blocks. Once a window is detected, it runs the window handler function and passes the window data as an argument. The window watch process guarantees that the window handler is called only once for the given coordination window. Moreover, it also guarantees that the window handler is called for all coordination windows. This is achieved by calling each handler in a separate goroutine so the watch loop does not block for long and the chance of missing a coordination window signal is negligible.The window handler function triggers the window processing logic. Specific steps of that logic are:
Coordination executor
The coordination executor is a component that is responsible for running the coordination procedure for the given wallet and coordination window. It is designed to encapsulate the logic of the procedure (coordination seed, communication, and so on). It also ensures that only one instance of the procedure is executed at a time. The executor is also responsible for assembling the coordination procedure's result and reporting all coordination faults detected during execution.
The design of the coordination executor is inspired by the existing signing and DKG executor. It attempts to fit the coordination procedure's logic into the existing codebase in an elegant way.
Coordination result processor
The coordination result processor goroutine listens for incoming coordination results and triggers the result handler function in a separate goroutine to ensure all results are processed independently.
The result handler function triggers the result processing logic. Specific steps of that logic are:
The proposal handlers are part of the existing codebase. They are responsible for the orchestration and execution of the proposed wallet actions.
Intersection with the existing chain-based coordination mechanism
The presented groundwork was built alongside the existing chain-based coordination mechanism. Some initial integration steps around data types were done. The existing mechanism will be gradually removed and replaced in the follow-up pull requests.
Next steps
The next steps (coarse-grained) on the way towards RFC 12 implementation are:
coordinationExecutor.coordinate
method)processCoordinationResult
function and refactornode
's handlers appropriately)WalletCoordinator
's events handlers and remove unnecessary code fromchain.go
)WalletCoordinator
's events during unproven transactions lookup