ethers-rs icon indicating copy to clipboard operation
ethers-rs copied to clipboard

Object Safe Connections

Open oliver-giersch opened this issue 2 years ago • 5 comments

This is the realization of the design proposed in #592.

Motivation

The current Transport trait is not object-safe, meaning it is not easily possible to dynamically abstract over different connection types at runtime. It is also heavily entangled with the Middleware trait, obscuring in some cases what happens, when API calls are made (or even, if API calls are made at all).

Solution

Rewrite Transport trait and implementations to be object-safe, untangle Middleware trait and move entirely to ethers-middleware, making it optional for certain use-cases.

Issues to be Resolved by this PR

  • #1154 - the rewritten Provider type will expose the Ethereum JSON-RPC in type-safe manner, with mostly a 1:1 mapping between RPC calls and exposed methods
  • #969 - with the new Provider API, the PendingTransaction type could/should be made generic over owned & borrowed providers
  • #876 - this is already implemented, the signature is async fn [Provider::]connect(url: &str) -> Result<Provider<Arc<dyn Connection>>, ProviderError>
  • #592

Points of Contention

Some points I would like to discuss before moving forward on them:

  1. There is a bunch of types in ethers-core that only exist because of the structure of the JSON-RPC API, such as SyncStatus (models the return type of eth_syncing) or BlockNumber (allows calling certain methods with either a block number or a generic tag like "latest"). I would like to move all those types to ethers_providers::types.
  2. The "meta-transport" implementations Quorum and ReadWrite. The latter in particular feels like something that could be easily handwritten by each user requiring such functionality and is not really worth the cost of maintaining it at a library level, but feel free to voice your concerns in the comments. Both could probably be "hackily" implemented as Connection impls by inspecting the "raw" request strings and searching for method call names.
  3. To me, ethers-providers should provide an API that fairly closely matches the Ethereum JSON-RPC API, so send_raw_transaction should just return a hash, get_block_by_number/get_block_by_hash should be distinct functions, etc. Convenience should be added on top of that at a higher level (i.e., for now, the Middleware trait).
  4. For now, I've changed the name of the trait from Transport to Connection, I feel like this better describes the concept being abstracted by it. I've also found it let me word doc comments less awkwardly and it more closely matches the terminology in the Ethereum API spec. Overall it may be undesirable to some, as it does lead to more API breakage I would think.

PR Checklist

  • [x] Implemented new Connection & DuplexConnection traits
  • [x] Implemented HTTP connection
  • [x] Implemented IPC connection
  • [ ] Implemented WS connection
  • [ ] Implemented Quorum/ReadWrite (discussion re potential removal?)
  • [ ] Implement full JSON-RPC API
  • [ ] Moved Middleware trait to ethers-middleware
  • [ ] Moved types that are only RPC-related from ethers-core to ethers-providers (discussion?)
  • [ ] Merge with ethers-providers
  • [ ] Added Tests
  • [ ] Added Documentation
  • [ ] Updated the changelog

oliver-giersch avatar May 15 '22 20:05 oliver-giersch