-
Notifications
You must be signed in to change notification settings - Fork 499
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
services/submitter: Prototype of Transaction Submission Service #4752
base: master
Are you sure you want to change the base?
Conversation
Thanks for getting this started, I'm super excited about the project. Error HandlingI think the next step to take here is to implement automatic resubmission on recoverable errors. Recoverable errors are:
Errors that are not recoverable:
All other errors indicate a bug in the package. Interface DesignI also think we need to simplify the interface exposed to the developer using this package. From their perspective, there should be three transaction statuses:
There should be no distinction between a transaction that has not been picked up from the store, one that has been retrieved from the store but not submitted, and one that has been submitted but has not been included in a ledger. |
WhatRefactors @bartekn's initial implementation of the transaction submitter to better manage concurrent transaction submission.
This PR also adds the following:
WhyThe existing implementation assigns transactions to channels that could still be working on submitting previously assigned transactions. This would cause sequence number errors and channel accounts would constantly have to reload their state, reconstruct transactions, and resubmit them. Using a buffered channel allows for:
|
NumChannels: uint(numChannels), | ||
Store: store, | ||
RootAccountSeed: os.Getenv("SUBMITTER_ROOT_SEED"), | ||
MaxBaseFee: uint(baseFee), |
Check failure
Code scanning / CodeQL
Incorrect conversion between integer types
What
This commit moves transaction submitter module from an old SDF project and adapts it to the current
stellar/go
API.Why
A service like this can be useful for organizations outside SDF. Also, in SDF we have multiple tx submitters in different projects, using a single, well-tested and battle proven code can save time and prevent some common mistakes.
How it works
TransactionSubmitter
is the main process responsible for submitting transactions. A transaction can be in one of four states:pending
- transaction waiting to be submitted,sending
- transaction loaded and queued to be submitted,sent
- transaction successfully sent (added to ledger)error
- error while sending.Every second
TransactionSubmitter
loadsTransactionPerSecond
transactions withpending
state from a DB and attempts to send them. In a DB transaction it changes their state tosending
.Next, one of
Channel
s is selected to actually submit tx with it's sequence number. Channels are used one after another. If tx is successfully included in the ledger the state is changed tosent
, otherwise toerror
. In case ofbad_seq
error channel state is automatically reloaded.Known limitations
The above algorithm is simple and prevents many common mistakes like attempting to send a transaction again on
error
case (which ex. can be a success but the200 OK
response was not delivered due to network issues).Below is a list of possible improvements to the system:
error
ed transactions. This is probably fine when the system is maintained by an experienced developer but it's not always a case. We could improve the algorithm to detect when theerror
is actually a final state:timebounds.max_time
and monitor ledgers to check if tx actually made it to the ledger in a given time.POST /transactions
call). Maybe we need an intermediate state? This state can be safely reverted topending
on system crash./fee_stats
endpoint in Horizon. As with previous points, txs that did not make it into ledger because of low fee should be resubmitted.PostgresStore
to support other DB engines.