Merge remote-tracking branch 'origin/feature/plugeth-test-plugin' into merge/geth-v1.12.0
This commit is contained in:
commit
6ed9390f9b
150
core/plugeth_injection_test.go
Normal file
150
core/plugeth_injection_test.go
Normal 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 = ¶ms.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")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
@ -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())
|
||||||
|
50
core/rawdb/plugeth_injection_test.go
Normal file
50
core/rawdb/plugeth_injection_test.go
Normal 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")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -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{}) }
|
||||||
|
@ -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))
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user