Add Rust client proposal (#9246)

* Add Rust client proposal

* Apply review feedback
This commit is contained in:
Greg Fitzgerald 2020-04-06 16:38:03 -06:00 committed by GitHub
parent 9a9fa5594d
commit a4e2ee99d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 0 deletions

View File

@ -121,3 +121,4 @@
* [Tick Verification](proposals/tick-verification.md)
* [Block Confirmation](proposals/block-confirmation.md)
* [ABI Management](proposals/abi-management.md)
* [Rust Clients](proposals/rust-clients.md)

View File

@ -0,0 +1,52 @@
# Rust Clients
## Problem
High-level tests, such as bench-tps, are written in terms of the `Client`
trait. When we execute these tests as part of the test suite, we use the
low-level `BankClient` implementation. When we need to run the same test
against a cluster, we use the `ThinClient` implementation. The problem with
that approach is that it means the trait will continually expand to include new
utility functions and all implementations of it need to add the new
functionality. By separating the user-facing object from the trait that abstracts
the network interface, we can expand the user-facing object to include all sorts
of useful functionality, such as the "spinner" from RpcClient, without concern
for needing to extend the trait and its implementations.
## Proposed Solution
Instead of implementing the `Client` trait, `ThinClient` should be constructed
with an implementation of it. That way, all utility functions currently in the
`Client` trait can move into `ThinClient`. `ThinClient` could then move into
`solana-sdk` since all its network dependencies would be in the implementation
of `Client`. We would then add a new implementation of `Client`, called
`ClusterClient`, and that would live in the `solana-client` crate, where
`ThinClient` currently resides.
After this reorg, any code needing a client would be written in terms of
`ThinClient`. In unit tests, the functionality would be invoked with
`ThinClient<BankClient>`, whereas `main()` functions, benchmarks and
integration tests would invoke it with `ThinClient<ClusterClient>`.
If higher-level components require more functionality than what could be
implemented by `BankClient`, it should be implemented by a second object
that implements a second trait, following the same pattern described here.
### Error Handling
The `Client` should use the existing `TransportError` enum for errors, except
that the `Custom(String)` field should be changed to `Custom(Box<dyn Error>)`.
### Implementation Strategy
1. Add new object to `solana-sdk`, `RpcClientTng`, where the `Tng` suffix is
temporary and stands for "The Next Generation"
2. Initialize `RpcClientTng` with a `SyncClient` implementation.
3. Add new object to `solana-sdk`, `ThinClientTng`; initialize it with
`RpcClientTng` and an `AsyncClient` implementation
4. Move all unit-tests from `BankClient` to `ThinClientTng<BankClient>`
5. Add `ClusterClient`
5. Move `ThinClient` users to `ThinClientTng<ClusterClient>`
6. Delete `ThinClient` and rename `ThinClientTng` to `ThinClient`
7. Move `RpcClient` users to new `ThinClient<ClusterClient>`
8. Delete `RpcClient` and rename `RpcClientTng` to `RpcClient`