-
Notifications
You must be signed in to change notification settings - Fork 885
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
Allow plugins to propose transactions during block creation #8268
Conversation
d85013c
to
4de05eb
Compare
selectedTransactions.add(transaction); | ||
transactionsByType | ||
.computeIfAbsent(transaction.getType(), type -> new ArrayList<>()) | ||
.add(transaction); | ||
receipts.add(receipt); | ||
cumulativeGasUsed += gasUsed; | ||
cumulativeBlobGasUsed += blobGasUsed; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why we are removing cumulativeBlobGasUsed ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before this class was used to both (1)track selection results and (2)managed some state for the selectors, now the 2 tasks have been separated and in this class are only kept the selection results(1) and since the cumulativeBlobGasUsed
is not needed as result, but only useful for the stateful selector it has been moved into the BlobSizeTransactionSelector
return selectorsStateManager.getSelectorWorkingState(this); | ||
} | ||
|
||
protected void setWorkingState(final S newState) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not completly sure about this name, for me it was the WorldState and after I saw that it's a long 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is about the selector specific state, for example the BlobSizeTransactionSelector
that needs to keep the cumulative count of how many blobs have been already added by previous txs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if it's better but maybe WorkingContext? SelectionContext?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure, we already have BlockSelectionContext
and TransactionEvaluationContext
here so it can also create confusion.
Do you think using state could be confusing just at a first look, and after reviewing the code for longer the distinction is clearer?
I can also rename this method to setSelectorWorkingState
, I thought it was redundant since it is in a selector class already, but if it helps readability then no problem
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's ok, maybe just add a comment to explain what is this state
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -29,37 +29,39 @@ | |||
* evaluating transactions based on block size. It checks if a transaction is too large for the | |||
* block and determines the selection result accordingly. | |||
*/ | |||
public class BlockSizeTransactionSelector extends AbstractTransactionSelector { | |||
public class BlockSizeTransactionSelector extends AbstractStatefulTransactionSelector<Long> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AbstractStatefulTransactionSelector. I feel that this name should be in conflict with Statefull and stateless worldstate. Just thniking I don't have a strong opinion about that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that state can refer to different things here, so one should read it along with transaction selector to fully qualify, not sure what could be another naming for this
category = "Core", | ||
elementType = "filter", | ||
printObject = true) | ||
public class StackTraceMatchFilter extends AbstractFilter { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this class needed for this PR ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not really, it is an helper to configure log4j to avoid logging some exception that are not relevant during the tests, do you prefer to have it in a separate PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No if It is necessary for your tests I think it's OK
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't finished the review, but this is my first round of comments
package org.hyperledger.besu.plugin.services.txselection; | ||
|
||
/** | ||
* This class represents an abstract plugin transaction selector which provides manage the selector |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
small typo to fix : which provides manage the selector
|
||
/** | ||
* Get the working state for this selector. A working state contains changes that have not yet | ||
* commited |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- typo fix : committed
transaction -> evaluateTransaction(new PendingTransaction.Local.Priority(transaction))); | ||
selectorsStateManager.blockSelectionStarted(); | ||
|
||
transactions.stream() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Streams are not good for performance especially when using map, so I prefer the the previous version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reverted
final PendingTransaction pendingTransaction) { | ||
@Override | ||
public TransactionSelectionResult evaluatePendingTransaction( | ||
final org.hyperledger.besu.datatypes.PendingTransaction pendingTransaction) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to import PendingTransaction with the whole package here ? is there another PendingTransaction ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, for example when we create the actual pending txs in the evaluateTransactions
method, while this method is from the interface and uses the PendingTransaction
interface
processTransaction(evaluationContext.getTransaction(), txWorldStateUpdater); | ||
processTransaction(evaluationContext.getTransaction()); | ||
|
||
txWorldStateUpdater.markTransactionBoundary(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate on why this is needed ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is needed in case more that one tx is processed before the commit, for example a plugin can only decide to commit only if txA and txB are both selected, so in this case you use the same world state updater first to execute txA and then txB, but without marking the tx boundary, it is possible that when executing txB there are some addresses already warm-up by txA, thus breaking the gas calculation.
This has no effect without plugin, since here we are committing after every selected, but provides flexibility for plugin to implement selection logic.
processTransaction(evaluationContext.getTransaction(), txWorldStateUpdater); | ||
processTransaction(evaluationContext.getTransaction()); | ||
|
||
txWorldStateUpdater.markTransactionBoundary(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this called before the commit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is called on StackedUpdater
so if I understood correctly it should be fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok just wanted to be sure we are not using it for Bonsai accumulator
4de05eb
to
01b729b
Compare
01b729b
to
de8c049
Compare
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
de8c049
to
4ac97a7
Compare
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, it would be great if we can have more coverage on BlockSizeTransactionSelector
class, as this PR changes the way cumulative gas is updated.
txWorldStateUpdater.commit(); | ||
blockWorldStateUpdater.commit(); | ||
for (final var pendingAction : selectedTxPendingActions) { | ||
pendingAction.run(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the executions will be sequential here, otherwise a use of an executor is more convenient if we want to have asynchronous executions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes this must be sequential and all pending actions must be completed before leaving the synchronized block
* @return a copy of the long | ||
*/ | ||
static long duplicateLong(final long l) { | ||
return l; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is a bit confusing for me as it returns the input param, I dont see why we need to call it in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is like the UnaryOperator::identity
method, since basically there is no need to duplicate a long, it is used by selectors that have a Long
as state like BlockSelectionContext
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
PR description
With this PR, plugins that could already apply custom rules during the evaluation of pending transactions for block inclusion, can now directly propose pending transactions for block inclusion. Of course plugin proposed pending transactions must pass all the filters and be processed successfully.
In order to propose transactions a plugin implements its selection logic extending
PluginTransactionSelectorFactory::selectPendingTransactions
method, via that method it has access to the pending block header and theBlockTransactionSelectionService
that is the core if the workflow, since it allows for evaluating pending transactions and depending on the result of the evaluations, the plugin can decide to either commit or rollback them.The process of evaluation a pending transaction, not only changes the world state, but also affected the internal state of some selectors, for example the selector that tracks the cumulative gas used in the block or the blobs numbers, we can refer to these selectors as stateful, and a common unified strategy has been introduce to support stateful selectors, via the
SelectorsStateManager
, that is now responsible to keep and manage the working and commited state for each stateful selector.Fixed Issue(s)
Thanks for sending a pull request! Have you done the following?
doc-change-required
label to this PR if updates are required.Locally, you can run these tests to catch failures early:
./gradlew spotlessApply
./gradlew build
./gradlew acceptanceTest
./gradlew integrationTest
./gradlew ethereum:referenceTests:referenceTests