Merge remote-tracking branch 'origin/feature/plugeth-test-plugin' into merge/geth-v1.12.0

This commit is contained in:
philip-morlier 2023-07-12 13:47:51 -07:00
commit 6ed9390f9b
6 changed files with 263 additions and 2 deletions

View File

@ -0,0 +1,150 @@
package core
import (
"hash"
"fmt"
"testing"
"math/big"
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"golang.org/x/crypto/sha3"
)
var (
config = &params.ChainConfig{
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
Ethash: new(params.EthashConfig),
}
signer = types.LatestSigner(config)
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
key2, _ = crypto.HexToECDSA("0202020202020202020202020202020202020202020202020202002020202020")
)
var makeTx = func(key *ecdsa.PrivateKey, nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *types.Transaction {
tx, _ := types.SignTx(types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data), signer, key)
return tx
}
var (
db = rawdb.NewMemoryDatabase()
gspec = &Genesis{
Config: config,
Alloc: GenesisAlloc{
common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{
Balance: big.NewInt(1000000000000000000), // 1 ether
Nonce: 0,
},
common.HexToAddress("0xfd0810DD14796680f72adf1a371963d0745BCc64"): GenesisAccount{
Balance: big.NewInt(1000000000000000000), // 1 ether
Nonce: math.MaxUint64,
},
},
}
)
type testHasher struct {
hasher hash.Hash
}
func newHasher() *testHasher {
return &testHasher{hasher: sha3.NewLegacyKeccak256()}
}
func (h *testHasher) Reset() {
h.hasher.Reset()
}
func (h *testHasher) Update(key, val []byte) {
h.hasher.Write(key)
h.hasher.Write(val)
}
func (h *testHasher) Hash() common.Hash {
return common.BytesToHash(h.hasher.Sum(nil))
}
func TestPlugethInjections(t *testing.T) {
blockchain, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
engine := ethash.NewFaker()
sp := NewStateProcessor(config, blockchain, engine)
txns := []*types.Transaction{
makeTx(key1, 0, common.Address{}, big.NewInt(1000), params.TxGas-1000, big.NewInt(875000000), nil),
}
block := GenerateBadBlock(gspec.ToBlock(), engine, txns, gspec.Config)
statedb, _ := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache, nil)
t.Run(fmt.Sprintf("test BlockProcessingError"), func(t *testing.T) {
called := false
injectionCalled = &called
metaInjectionCalled = &called
_, _, _, _ = sp.Process(block, statedb, vm.Config{})
if *injectionCalled != true {
t.Fatalf("pluginBlockProcessingError injection in stateProcessor.Process() not called")
}
if *metaInjectionCalled != true {
t.Fatalf("metaTracer.BlockProcessingError injection in stateProcessor.Process() not called")
}
})
t.Run(fmt.Sprintf("test Reorg"), func(t *testing.T) {
called := false
injectionCalled = &called
// the transaction has to be initialized with a different gas price than the previous tx in order to trigger a reorg
txns2 := []*types.Transaction{
makeTx(key1, 0, common.Address{}, big.NewInt(1000), params.TxGas-1000, big.NewInt(875000001), nil),
}
block2 := GenerateBadBlock(gspec.ToBlock(), engine, txns2, gspec.Config)
_, _ = blockchain.writeBlockAndSetHead(block, []*types.Receipt{}, []*types.Log{}, statedb, false)
_ = blockchain.reorg(block.Header(), block2)
if *injectionCalled != true {
t.Fatalf("pluginReorg injection in blockChain.Reorg() not called")
}
})
t.Run(fmt.Sprintf("test NewSideBlock"), func(t *testing.T) {
called := false
injectionCalled = &called
TestReorgToShorterRemovesCanonMapping(t)
if *injectionCalled != true {
t.Fatalf("pluginNewSideBlock injection in blockChain.writeBlockAndSetHead() not called")
}
})
}

View File

@ -18,6 +18,9 @@ import (
"github.com/openrelayxyz/plugeth-utils/core" "github.com/openrelayxyz/plugeth-utils/core"
) )
var injectionCalled *bool
var metaInjectionCalled *bool
func PluginPreProcessBlock(pl *plugins.PluginLoader, block *types.Block) { func PluginPreProcessBlock(pl *plugins.PluginLoader, block *types.Block) {
fnList := pl.Lookup("PreProcessBlock", func(item interface{}) bool { fnList := pl.Lookup("PreProcessBlock", func(item interface{}) bool {
_, ok := item.(func(core.Hash, uint64, []byte)) _, ok := item.(func(core.Hash, uint64, []byte))
@ -68,6 +71,12 @@ func PluginBlockProcessingError(pl *plugins.PluginLoader, tx *types.Transaction,
} }
} }
func pluginBlockProcessingError(tx *types.Transaction, block *types.Block, err error) { func pluginBlockProcessingError(tx *types.Transaction, block *types.Block, err error) {
if injectionCalled != nil {
called := true
injectionCalled = &called
}
if plugins.DefaultPluginLoader == nil { if plugins.DefaultPluginLoader == nil {
log.Warn("Attempting BlockProcessingError, but default PluginLoader has not been initialized") log.Warn("Attempting BlockProcessingError, but default PluginLoader has not been initialized")
return return
@ -160,6 +169,7 @@ func pluginNewSideBlock(block *types.Block, hash common.Hash, logs []*types.Log)
} }
func PluginReorg(pl *plugins.PluginLoader, commonBlock *types.Block, oldChain, newChain types.Blocks) { func PluginReorg(pl *plugins.PluginLoader, commonBlock *types.Block, oldChain, newChain types.Blocks) {
fnList := pl.Lookup("Reorg", func(item interface{}) bool { fnList := pl.Lookup("Reorg", func(item interface{}) bool {
_, ok := item.(func(core.Hash, []core.Hash, []core.Hash)) _, ok := item.(func(core.Hash, []core.Hash, []core.Hash))
return ok return ok
@ -179,6 +189,12 @@ func PluginReorg(pl *plugins.PluginLoader, commonBlock *types.Block, oldChain, n
} }
} }
func pluginReorg(commonBlock *types.Block, oldChain, newChain types.Blocks) { func pluginReorg(commonBlock *types.Block, oldChain, newChain types.Blocks) {
if injectionCalled != nil {
called := true
injectionCalled = &called
}
if plugins.DefaultPluginLoader == nil { if plugins.DefaultPluginLoader == nil {
log.Warn("Attempting Reorg, but default PluginLoader has not been initialized") log.Warn("Attempting Reorg, but default PluginLoader has not been initialized")
return return
@ -213,6 +229,12 @@ func (mt *metaTracer) PreProcessTransaction(tx *types.Transaction, block *types.
} }
} }
func (mt *metaTracer) BlockProcessingError(tx *types.Transaction, block *types.Block, err error) { func (mt *metaTracer) BlockProcessingError(tx *types.Transaction, block *types.Block, err error) {
if metaInjectionCalled != nil {
called := true
metaInjectionCalled = &called
}
if len(mt.tracers) == 0 { return } if len(mt.tracers) == 0 { return }
blockHash := core.Hash(block.Hash()) blockHash := core.Hash(block.Hash())
transactionHash := core.Hash(tx.Hash()) transactionHash := core.Hash(tx.Hash())

View File

@ -0,0 +1,50 @@
package rawdb
import (
"fmt"
"testing"
"math/big"
"github.com/ethereum/go-ethereum/ethdb"
)
func TestPlugethInjections(t *testing.T) {
var valuesRaw [][]byte
var valuesRLP []*big.Int
for x := 0; x < 100; x++ {
v := getChunk(256, x)
valuesRaw = append(valuesRaw, v)
iv := big.NewInt(int64(x))
iv = iv.Exp(iv, iv, nil)
valuesRLP = append(valuesRLP, iv)
}
tables := map[string]bool{"raw": true, "rlp": false}
f, _ := newFreezerForTesting(t, tables)
t.Run(fmt.Sprintf("test plugeth injections"), func(t *testing.T) {
called := false
modifyAncientsInjection = &called
_, _ = f.ModifyAncients(func(op ethdb.AncientWriteOp) error {
appendRawInjection = &called
_ = op.AppendRaw("raw", uint64(0), valuesRaw[0])
if *appendRawInjection != true {
t.Fatalf("pluginTrackUpdate injection in AppendRaw not called")
}
appendInjection = &called
_ = op.Append("rlp", uint64(0), valuesRaw[0])
if *appendInjection != true {
t.Fatalf("pluginTrackUpdate injection in Append not called")
}
return nil
})
if *modifyAncientsInjection != true {
t.Fatalf("pluginCommitUpdate injection in ModifyAncients not called")
}
})
}

View File

@ -2,18 +2,33 @@ package rawdb
import ( import (
"sync"
"github.com/ethereum/go-ethereum/plugins" "github.com/ethereum/go-ethereum/plugins"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"sync"
) )
var ( var (
freezerUpdates map[uint64]map[string]interface{} freezerUpdates map[uint64]map[string]interface{}
lock sync.Mutex lock sync.Mutex
modifyAncientsInjection *bool
appendRawInjection *bool
appendInjection *bool
) )
func PluginTrackUpdate(num uint64, kind string, value interface{}) { func PluginTrackUpdate(num uint64, kind string, value interface{}) {
if appendRawInjection != nil {
called := true
appendRawInjection = &called
}
if appendInjection != nil {
called := true
appendInjection = &called
}
lock.Lock() lock.Lock()
defer lock.Unlock() defer lock.Unlock()
if freezerUpdates == nil { freezerUpdates = make(map[uint64]map[string]interface{}) } if freezerUpdates == nil { freezerUpdates = make(map[uint64]map[string]interface{}) }
@ -26,6 +41,12 @@ func PluginTrackUpdate(num uint64, kind string, value interface{}) {
} }
func pluginCommitUpdate(num uint64) { func pluginCommitUpdate(num uint64) {
if modifyAncientsInjection != nil {
called := true
modifyAncientsInjection = &called
}
if plugins.DefaultPluginLoader == nil { if plugins.DefaultPluginLoader == nil {
log.Warn("Attempting CommitUpdate, but default PluginLoader has not been initialized") log.Warn("Attempting CommitUpdate, but default PluginLoader has not been initialized")
return return
@ -34,6 +55,7 @@ func pluginCommitUpdate(num uint64) {
} }
func PluginCommitUpdate(pl *plugins.PluginLoader, num uint64) { func PluginCommitUpdate(pl *plugins.PluginLoader, num uint64) {
lock.Lock() lock.Lock()
defer lock.Unlock() defer lock.Unlock()
if freezerUpdates == nil { freezerUpdates = make(map[uint64]map[string]interface{}) } if freezerUpdates == nil { freezerUpdates = make(map[uint64]map[string]interface{}) }

View File

@ -151,7 +151,6 @@ func utilsToGethTransactions(transactions []*ptypes.Transaction) []*types.Transa
} }
return txs return txs
} }
func utilsToGethWithdrawals(withdrawals []*ptypes.Withdrawal) []*types.Withdrawal { func utilsToGethWithdrawals(withdrawals []*ptypes.Withdrawal) []*types.Withdrawal {
if withdrawals == nil { return nil } if withdrawals == nil { return nil }
pwithdrawals := make([]*types.Withdrawal, len(withdrawals)) pwithdrawals := make([]*types.Withdrawal, len(withdrawals))

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"reflect" "reflect"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/plugins"
) )
// Is t context.Context or *context.Context? // Is t context.Context or *context.Context?
@ -128,7 +129,24 @@ func callbackifyChanPubSub(receiver, fn reflect.Value) *callback {
return c return c
} }
func RPCSubscription(pl *plugins.PluginLoader) {
fnList := pl.Lookup("RPCSubscriptionTest", func(item interface{}) bool {
_, ok := item.(func())
return ok
})
for _, fni := range fnList {
if fn, ok := fni.(func()); ok {
fn()
}
}
}
func pluginExtendedCallbacks(callbacks map[string]*callback, receiver reflect.Value) { func pluginExtendedCallbacks(callbacks map[string]*callback, receiver reflect.Value) {
if plugins.DefaultPluginLoader == nil {
log.Warn("Attempting RPCSubscriptionTest, but default PluginLoader has not been initialized")
return
}
RPCSubscription(plugins.DefaultPluginLoader)
typ := receiver.Type() typ := receiver.Type()
for m := 0; m < typ.NumMethod(); m++ { for m := 0; m < typ.NumMethod(); m++ {
method := typ.Method(m) method := typ.Method(m)