-
Notifications
You must be signed in to change notification settings - Fork 207
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
Refactor the miner #1545
Refactor the miner #1545
Conversation
This is b/c IPC does not play nice with long temp dirs.
Don't have a shared "environment", but create one per block production.
This reverts commit d5ec1e6.
Continuing to follow the convention that the receiver is modified while passed in parameters are not.
Now the miner only has one go-routine.
// addParentSeal blocks for up to 500ms waiting for the core to reach the target sequence. | ||
// Prepare is called from non-validators, so don't bother with the parent seal unless this | ||
// block is to be proposed instead of for the local state. | ||
if sb.IsValidating() { |
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 awckward...
we have a method call addParentSeal()
that does a sleep
. As a reader, why would adding a seal implies sleeping?
And then i have a Prepare() than ask if we are validating...
I know this is not from this PR, and the ware only bringing up the awckarness to the surface. But i wonder if there's a clearer way to express this.
@@ -223,6 +223,7 @@ func makeBlockWithoutSeal(chain *core.BlockChain, engine *Backend, parent *types | |||
// The worker that calls Prepare is the one filling the Coinbase | |||
header.Coinbase = engine.address | |||
engine.Prepare(chain, header) | |||
time.Sleep(time.Until(time.Unix(int64(header.Time), 0))) |
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.
do we need to sleep? would be ncie if we didn't as i've seen we are not really testing this behaviuor, but just need to create blocks on the test
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.
The tests have issues if we don't sleep at all, but it's definitely possible to sleep for less time.
} | ||
|
||
// prepareBlock intializes a new blockState that is ready to have transaction included to. | ||
func prepareBlock(w *worker) (*blockState, error) { |
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 would say this is cheating: so, to avoid having a worker method in another file, you make it a standalone function...
but you access worker state is if where your private state.
for example, using the Lock to access internal state. This can be nasty, since the whole idea of having an object with "private state" is that you don't need to worry about anyone else when modifying it... that's encapsulation. But we don't have any of that here.
I can look to the other side for now, if we want to get this to master, but it is worth mentioning nonetheless
cpy[i] = new(types.Log) | ||
*cpy[i] = *l | ||
} | ||
w.pendingLogsFeed.Send(cpy) |
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.
to me it's ackward that we are accessing an internal feed object on the worker here
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.
Yea. This is the same thing as above that the miner used to be so entangled in the block production that making it only depend on specific fields is a pain.
} | ||
} | ||
recommit = time.Duration(int64(next)) | ||
w.updatePendingBlock(b) |
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.
asking again, does it make sense to have a pending block with no transactions?
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.
We need to make sure that the pending block is the latest head block
} | ||
for { | ||
select { | ||
case <-w.startCh: |
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.
if we call start() twice that means we will cancel current work and start again, feature or bug?
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.
That's correct. Unintended consequence that doesn't really matter. We want to cancel the pending block and start proposing blocks on start
. It would be possible to gate sending to the start channel on the current miner state, but it doesn't seem like a big issue.
|
||
var coalescedLogs []*types.Log | ||
txsCh := make(chan core.NewTxsEvent, txChanSize) |
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.
shouldn't we try to get txpool configured size to set this size?
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.
We could, but this isn't regressing.
* Remove unused miner flags and configuration options * Remove threads flag. Mark GasPrice as deprecated - Removes MinerThreads flags, it was not used. - Marks GasPrice flag as deprecated - Maps miner.Start/Stop method on the web3js api * pr comment
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! Great work!
Description
This refactors the miner with a couple goals
I worked towards these goals by
miner/block.go
blockState
struct).engine.Prepare
Other changes
miner/miner.go
to simplify the start up logic.Tested
Unit tests still pass.
Tested end to end on
trianglesphere/miner_refactor_v2
TODO: test that this fixes the pending bug.
Related issues
Backwards compatibility
Yes