Skip to content

Abstract the transaction signature verification in block processor #32782

@rjl493456442

Description

@rjl493456442

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 ...
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions