Refactor plugin system
When the plugin loader itself had to know the types in the arguments and return values of the plugin functions, it was very difficult to avoid import loops, given that the types were often defined in the same package that needed to invoke the plugins. Under this model, the plugin loader has much less knowledge of the plugins themselves, and within each package we define functions to interact with the plugins.
This commit is contained in:
@@ -1,37 +0,0 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
|
||||
type StateDB interface {
|
||||
Error() error
|
||||
GetLogs(hash common.Hash) []*types.Log
|
||||
Logs() []*types.Log
|
||||
Preimages() map[common.Hash][]byte
|
||||
Exist(addr common.Address) bool
|
||||
Empty(addr common.Address) bool
|
||||
GetBalance(addr common.Address) *big.Int
|
||||
GetNonce(addr common.Address) uint64
|
||||
TxIndex() int
|
||||
BlockHash() common.Hash
|
||||
GetCode(addr common.Address) []byte
|
||||
GetCodeSize(addr common.Address) int
|
||||
GetCodeHash(addr common.Address) common.Hash
|
||||
GetState(addr common.Address, hash common.Hash) common.Hash
|
||||
GetProof(addr common.Address) ([][]byte, error)
|
||||
GetProofByHash(addrHash common.Hash) ([][]byte, error)
|
||||
GetStorageProof(a common.Address, key common.Hash) ([][]byte, error)
|
||||
GetStorageProofByHash(a common.Address, key common.Hash) ([][]byte, error)
|
||||
GetCommittedState(addr common.Address, hash common.Hash) common.Hash
|
||||
HasSuicided(addr common.Address) bool
|
||||
ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error
|
||||
GetRefund() uint64
|
||||
AddressInAccessList(addr common.Address) bool
|
||||
SlotInAccessList(addr common.Address, slot common.Hash) (addressPresent bool, slotPresent bool)
|
||||
}
|
||||
+28
-205
@@ -2,15 +2,8 @@ package plugins
|
||||
|
||||
import (
|
||||
"plugin"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||
// "github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
"flag"
|
||||
"io/ioutil"
|
||||
@@ -29,19 +22,32 @@ type TracerResult interface {
|
||||
|
||||
|
||||
type PluginLoader struct{
|
||||
Plugins []plugin.Plugin
|
||||
Tracers map[string]func(StateDB)TracerResult
|
||||
StateHooks []interface{} // TODO: Set interface
|
||||
// RPCPlugins []APILoader
|
||||
Plugins []*plugin.Plugin
|
||||
Subcommands map[string]Subcommand
|
||||
Flags []*flag.FlagSet
|
||||
CreateConsensusEngine func(stack *node.Node, chainConfig *params.ChainConfig, config *ethash.Config, notify []string, noverify bool, db ethdb.Database) consensus.Engine
|
||||
UpdateBlockchainVMConfig func(*vm.Config)
|
||||
PreProcessBlockList []func(*types.Block)
|
||||
PreProcessTransactionList []func(*types.Transaction, *types.Block, int)
|
||||
BlockProcessingErrorList []func(*types.Transaction, *types.Block, error)
|
||||
PostProcessTransactionList []func(*types.Transaction, *types.Block, int, *types.Receipt)
|
||||
PostProcessBlockList []func(*types.Block)
|
||||
LookupCache map[string][]interface{}
|
||||
}
|
||||
|
||||
func (pl *PluginLoader) Lookup(name string, validate func(interface{}) bool) []interface{} {
|
||||
if v, ok := pl.LookupCache[name]; ok { return v }
|
||||
results := []interface{}{}
|
||||
for _, plugin := range pl.Plugins {
|
||||
if v, err := plugin.Lookup(name); err == nil {
|
||||
if validate(v) {
|
||||
results = append(results, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
pl.LookupCache[name] = results
|
||||
return results
|
||||
}
|
||||
|
||||
func Lookup(name string, validate func(interface{}) bool) []interface{} {
|
||||
if DefaultPluginLoader == nil {
|
||||
log.Warn("Lookup attempted, but PluginLoader is not initialized", "name", name)
|
||||
return []interface{}{}
|
||||
}
|
||||
return DefaultPluginLoader.Lookup(name, validate)
|
||||
}
|
||||
|
||||
|
||||
@@ -50,21 +56,19 @@ var DefaultPluginLoader *PluginLoader
|
||||
|
||||
func NewPluginLoader(target string) (*PluginLoader, error) {
|
||||
pl := &PluginLoader{
|
||||
Plugins: []plugin.Plugin,
|
||||
Plugins: []*plugin.Plugin{},
|
||||
// RPCPlugins: []APILoader{},
|
||||
Subcommands: make(map[string]Subcommand),
|
||||
Tracers: make(map[string]func(StateDB)TracerResult),
|
||||
Flags: []*flag.FlagSet{},
|
||||
LookupCache: make(map[string][]interface{}),
|
||||
// CreateConsensusEngine: ethconfig.CreateConsensusEngine,
|
||||
UpdateBlockchainVMConfig: func(cfg *vm.Config) {},
|
||||
// UpdateBlockchainVMConfig: func(cfg *vm.Config) {},
|
||||
}
|
||||
files, err := ioutil.ReadDir(target)
|
||||
if err != nil {
|
||||
log.Warn("Could not load plugins directory. Skipping.", "path", target)
|
||||
return pl, nil
|
||||
}
|
||||
setConsensus := false
|
||||
setUpdateBCVMCfg := false
|
||||
for _, file := range files {
|
||||
fpath := path.Join(target, file.Name())
|
||||
if !strings.HasSuffix(file.Name(), ".so") {
|
||||
@@ -100,97 +104,7 @@ func NewPluginLoader(target string) (*PluginLoader, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
tr, err := plug.Lookup("Tracers")
|
||||
if err == nil {
|
||||
tracers, ok := tr.(*map[string]func(StateDB)TracerResult)
|
||||
if !ok {
|
||||
log.Warn("Could not cast plugin.Tracers to `map[string]vm.Tracer`", "file", fpath)
|
||||
} else {
|
||||
for k, v := range *tracers {
|
||||
if _, ok := pl.Tracers[k]; ok {
|
||||
log.Warn("Tracer redeclared", "file", fpath, "tracer", k)
|
||||
}
|
||||
pl.Tracers[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
ce, err := plug.Lookup("CreateConsensusEngine")
|
||||
if err == nil {
|
||||
cce, ok := ce.(func (stack *node.Node, chainConfig *params.ChainConfig, config *ethash.Config, notify []string, noverify bool, db ethdb.Database) consensus.Engine)
|
||||
if !ok {
|
||||
log.Warn("Could not cast plugin.CreateConsensusEngine to appropriate function", "file", fpath)
|
||||
} else {
|
||||
if setConsensus {
|
||||
log.Warn("CreateConsensusEngine redeclared", "file", fpath)
|
||||
}
|
||||
pl.CreateConsensusEngine = cce
|
||||
setConsensus = true
|
||||
}
|
||||
}
|
||||
vmcfgu, err := plug.Lookup("UpdateBlockchainVMConfig")
|
||||
if err == nil {
|
||||
vmcfgfn, ok := vmcfgu.(func(*vm.Config))
|
||||
if !ok {
|
||||
log.Warn("Could not cast plugin.UpdateBlockchainVMConfig to appropriate function", "file", fpath)
|
||||
} else {
|
||||
if setUpdateBCVMCfg {
|
||||
log.Warn("UpdateBlockchainVMConfig redeclared", "file", fpath)
|
||||
}
|
||||
pl.UpdateBlockchainVMConfig = vmcfgfn
|
||||
setUpdateBCVMCfg = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
prepb, err := plug.Lookup("PreProcessBlock")
|
||||
if err == nil {
|
||||
prepbfn, ok := prepb.(func(*types.Block))
|
||||
if !ok {
|
||||
log.Warn("Could not cast plugin.PreProcessBlock to appropriate function", "file", fpath)
|
||||
} else {
|
||||
pl.PreProcessBlockList = append(pl.PreProcessBlockList, prepbfn)
|
||||
}
|
||||
}
|
||||
prept, err := plug.Lookup("PreProcessTransaction")
|
||||
if err == nil {
|
||||
preptfn, ok := prept.(func(*types.Transaction, *types.Block, int))
|
||||
if !ok {
|
||||
log.Warn("Could not cast plugin.PreProcessTransaction to appropriate function", "file", fpath)
|
||||
} else {
|
||||
pl.PreProcessTransactionList = append(pl.PreProcessTransactionList, preptfn)
|
||||
}
|
||||
}
|
||||
bpe, err := plug.Lookup("BlockProcessingError")
|
||||
if err == nil {
|
||||
bpefn, ok := bpe.(func(*types.Transaction, *types.Block, error))
|
||||
if !ok {
|
||||
log.Warn("Could not cast plugin.BlockProcessingError to appropriate function", "file", fpath)
|
||||
} else {
|
||||
pl.BlockProcessingErrorList = append(pl.BlockProcessingErrorList, bpefn)
|
||||
}
|
||||
}
|
||||
prept, err := plug.Lookup("PostProcessTransaction")
|
||||
if err == nil {
|
||||
preptfn, ok := prept.(func(*types.Transaction, *types.Block, int, *types.Receipt))
|
||||
if !ok {
|
||||
log.Warn("Could not cast plugin.PostProcessTransaction to appropriate function", "file", fpath)
|
||||
} else {
|
||||
pl.PostProcessTransactionList = append(pl.PostProcessTransactionList, preptfn)
|
||||
}
|
||||
}
|
||||
prepb, err := plug.Lookup("PostProcessBlock")
|
||||
if err == nil {
|
||||
prepbfn, ok := prepb.(func(*types.Block))
|
||||
if !ok {
|
||||
log.Warn("Could not cast plugin.PostProcessBlock to appropriate function", "file", fpath)
|
||||
} else {
|
||||
pl.PostProcessBlockList = append(pl.PostProcessBlockList, prepbfn)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
pl.Plugins = append(pl.Plugins, plug)
|
||||
}
|
||||
return pl, nil
|
||||
}
|
||||
@@ -227,94 +141,3 @@ func ParseFlags(args []string) bool {
|
||||
}
|
||||
return DefaultPluginLoader.ParseFlags(args)
|
||||
}
|
||||
|
||||
func (pl *PluginLoader) GetTracer(s string) (func(StateDB)TracerResult, bool) {
|
||||
tr, ok := pl.Tracers[s]
|
||||
return tr, ok
|
||||
}
|
||||
|
||||
func GetTracer(s string) (func(StateDB)TracerResult, bool) {
|
||||
if DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting GetTracer, but default PluginLoader has not been initialized")
|
||||
return nil, false
|
||||
}
|
||||
return DefaultPluginLoader.GetTracer(s)
|
||||
}
|
||||
|
||||
// func CreateConsensusEngine(stack *node.Node, chainConfig *params.ChainConfig, config *ethash.Config, notify []string, noverify bool, db ethdb.Database) consensus.Engine {
|
||||
// if DefaultPluginLoader == nil {
|
||||
// log.Warn("Attempting CreateConsensusEngine, but default PluginLoader has not been initialized")
|
||||
// return ethconfig.CreateConsensusEngine(stack, chainConfig, config, notify, noverify, db)
|
||||
// }
|
||||
// return DefaultPluginLoader.CreateConsensusEngine(stack, chainConfig, config, notify, noverify, db)
|
||||
// }
|
||||
|
||||
func UpdateBlockchainVMConfig(cfg *vm.Config) {
|
||||
if DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting UpdateBlockchainVMConfig, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
DefaultPluginLoader.UpdateBlockchainVMConfig(cfg)
|
||||
}
|
||||
|
||||
|
||||
func (pl *PluginLoader) PreProcessBlock(block *types.Block) {
|
||||
for _, fn := range pl.PreProcessBlockList {
|
||||
fn(block)
|
||||
}
|
||||
}
|
||||
func PreProcessBlock(block *types.Block) {
|
||||
if DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting PreProcessBlock, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
DefaultPluginLoader.PreProcessBlock(block)
|
||||
}
|
||||
func (pl *PluginLoader) PreProcessTransaction(tx *types.Transaction, block *types.Block, i int) {
|
||||
for _, fn := range pl.PreProcessTransactionList {
|
||||
fn(tx, block, i)
|
||||
}
|
||||
}
|
||||
func PreProcessTransaction(tx *types.Transaction, block *types.Block, i int) {
|
||||
if DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting PreProcessTransaction, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
DefaultPluginLoader.PreProcessTransaction(tx, block, i)
|
||||
}
|
||||
func (pl *PluginLoader) BlockProcessingError(tx *types.Transaction, block *types.Block, err error) {
|
||||
for _, fn := range pl.BlockProcessingErrorList {
|
||||
fn(tx, block, err)
|
||||
}
|
||||
}
|
||||
func BlockProcessingError(tx *types.Transaction, block *types.Block, err error) {
|
||||
if DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting BlockProcessingError, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
DefaultPluginLoader.BlockProcessingError(tx, block, err)
|
||||
}
|
||||
func (pl *PluginLoader) PostProcessTransaction(tx *types.Transaction, block *types.Block, i int, receipt *types.Receipt) {
|
||||
for _, fn := range pl.PostProcessTransactionList {
|
||||
fn(tx, block, i, receipt)
|
||||
}
|
||||
}
|
||||
func PostProcessTransaction(tx *types.Transaction, block *types.Block, i int, receipt *types.Receipt) {
|
||||
if DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting PostProcessTransaction, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
DefaultPluginLoader.PostProcessTransaction(tx, block, i, receipt)
|
||||
}
|
||||
func (pl *PluginLoader) PostProcessBlock(block *types.Block) {
|
||||
for _, fn := range pl.PostProcessBlockList {
|
||||
fn(block)
|
||||
}
|
||||
}
|
||||
func PostProcessBlock(block *types.Block) {
|
||||
if DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting PostProcessBlock, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
DefaultPluginLoader.PostProcessBlock(block)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user