Skip to content

Like a thread pool, but for signing and broadcasting transactions

Notifications You must be signed in to change notification settings

shaurya947/ethers-signer-pool

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 

Repository files navigation

ethers-signer-pool

This library provides a utility built on top of the ethers crate. The purpose of the utility is to provide a pool of signers (wallets) that can process an arbitrary number of transactions concurrently. As such, a user of this library only needs to instantiate a SignerPool once with a middleware (provider), as well as a list of signing keys. From that point on, the user can simply interface with the library by passing in a list of function calls that encapsulate the transactions that the user would like executed, and the signer pool will schedule each transaction on an appropriate signer. Transaction broadcast and confirmation is done in a new task so as to introduce concurrency where it matters most.

High-level architecture

The SignerPool can be broken down into 4 parts: the API, the dispatcher task, the signers, and the futures/tasks used for broadcasting and confirmations.

image

  • User sends list of function calls to API and expects a list of results wrapped inside a future.
  • API receives a list of function calls from the User and maps each one into a new compound object TXWithOneshot which contains a oneshot sender in addition to the function call. API sends TXWithOneshot objects to the dispatcher via a channel.
  • API awaits messages on the list of oneshot receivers and returns a list of the received results back to the user.
  • Dispatcher receives TXWithOneshot instances from the API in a channel. It manages an internal nonce of its own. It assings each incoming function call a nonce, and stores the oneshot sender in a [nonce=>oneshot sender] mapping. It then calculates the estimated gas cost of the transaction, and packages the function call + nonce into a new compound object TXWithInternalNonce and looks for an appropriate signer to handle the transaction. Idle signers are checked first. Then busy signers are checked.
    • If an idle signer is picked, its state is changed to busy with a pending spent amount equal to the estimated gas cost of the transaction, and an object with the TX's estimated cost + internal nonce is added to the signer's active set.
    • If a busy signer is picked, its pending spend amount and active set are added to accordingly.
  • Once a signer is picked, a new task is spawned for broadcasting the TX and waiting for its confirmation. This task is given a clone of a sender end of a channel that is shared between all TX tasks and the dispatcher. This tasks returns the result of the broadcast (along with some other identifying information about the signer and the broadcasted transaction) back to the dispatcher using the provided sender.
  • The dispatcher is listening for TX results at the receiving end of the channel whose senders are given to the TX broadcast tasks. When it receives a message on this channel it does two things:
    • It updates the particular signer's balance and updates its state (makes it less busy or idle)
    • It finds the oneshot sender corresponding to the particular TX and sends the result/error down

TODOs

  • Add example code with usage to top of README
  • Introduce custom errors and resolve TODOs marked in code related to error handling
  • Add unit tests for signer and dispatcher modules, along with some integration tests
  • Add in-code documentation to prepare crate for publishing

About

Like a thread pool, but for signing and broadcasting transactions

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages