-
Notifications
You must be signed in to change notification settings - Fork 21.4k
Description
This is a feature request from tenderly team
We have another small proposal with the same theme of making StateProcessor usable as a library that we’d like to get your feedback on.
Currently, when processing blocks with StateProcessor, full cryptographic signature verification is enforced since a chain fork based signer is created via types.MakeSigner(), and then when Transactions are converted to Messages via TransactionToMessage, types.Sender() is called to fetch the sender address and verify the signature in the process of doing so.
This makes it impossible to bypass signature verification when using StateProcessor, and for testing/simulation scenarios, one might indeed want to skip it entirely, similar to how it’s done for eth_call .
What we’d like to propose is along the lines of adding a new SignerFactory interface which mirrors the existing MakeSigner pattern, with a “standard” fork-based implementation which would just call into types.MakeSigner() , leaving the default behaviour to be the same and fully backwards compatible, but also allowing for custom signer logic to be added. Here’s some code around how it could look like:
// transaction_signing.go
type SignerFactory interface {
MakeSigner(config *params.ChainConfig, blockNumber *big.Int, blockTime uint64) Signer
}
var _ SignerFactory = (*StandardSignerFactory)(nil)
type StandardSignerFactory struct{}
func NewStandardSignerFactory() *StandardSignerFactory {
return &StandardSignerFactory{}
}
func (ssf *StandardSignerFactory) MakeSigner(config *params.ChainConfig, blockNumber *big.Int, blockTime uint64) Signer {
return MakeSigner(config, blockNumber, blockTime)
}
// state_processor.go
// StateProcessor is a basic Processor, which takes care of transitioning
// state from one point to another.
//
// StateProcessor implements Processor.
type StateProcessor struct {
config *params.ChainConfig
chain ChainContext
signerFactory types.SignerFactory
}
// NewStateProcessor initialises a new StateProcessor.
func NewStateProcessor(config *params.ChainConfig, chain ChainContext) *StateProcessor {
return &StateProcessor{
config: config,
chain: chain,
signerFactory: types.NewStandardSignerFactory(),
}
}
// NewStateProcessorWithSignerFactory initialises a new StateProcessor with a specified types.SignerFactory.
func NewStateProcessorWithSignerFactory(config *params.ChainConfig, chain ChainContext, signerFactory types.SignerFactory) *StateProcessor {
return &StateProcessor{
config: config,
chain: chain,
signerFactory: signerFactory,
}
}
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (*ProcessResult, error) {
// ... existing logic ...
var (
context vm.BlockContext
signer = p.signerFactory.MakeSigner(p.chain.Config(), header.Number, header.Time)
)
// ... existing logic ...
}