## Why this should be merged
Fixes a potential race in parallel handler where the goroutine that
closes `whenProcessed` could observe a re-assigned channel for the next
block, leading to an incorrect close and possible double-close panic.
## How this works
`finishBlock()` waits for the channel to be closed by the goroutine,
instead of for the `WaitGroup` that closes _just_ before it, which is
what allowed the race.
## How this was tested
It's not possible to include a specific test. This PR therefore also
includes thorough documentation of every per-block goroutine and when it
is guaranteed to complete.
---------
Co-authored-by: Arran Schlosberg <me@arranschlosberg.com>
## Why this should be merged
EVM parallel co-processors that interface with the regular transaction
path via precompiles.
## How this works
Introduces the `parallel.Processor`, which orchestrates a set of
`parallel.Handler`s. Each `Handler` performs arbitrary, strongly typed
processing of any sub-set of transactions in a block and makes its
results available to a precompile and/or a post-block method for
persisting state. Although stateful, `Handler`s can only read the
pre-block and post-block state, which isolates them from conflicts with
the regular transaction path.
There is deliberately no support for a precompile to "write" to a
`Handler`, only to "read". This is because the transaction might still
revert, which would also have to be communicated to the `Handler`,
resulting in unnecessary complexity. Logs/events are the recommended
approach for precompile -> `Handler` communication, to be read from the
`types.Receipts` at the end of the block.
## How this was tested
Integration tests covering:
1. Selection of transactions to process + end-to-end plumbing of data
through a `Handler`.
2. Registration as a precompile, exercised with actual transaction
processing, and demonstrating log + return-data correctness.
---------
Signed-off-by: Arran Schlosberg <519948+ARR4N@users.noreply.github.com>