Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eth/protocols/eth: add protocol handler fuzzers #30417

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 80 additions & 2 deletions eth/protocols/eth/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
package eth

import (
"bytes"
"math"
"math/big"
"math/rand"
"testing"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
Expand All @@ -37,6 +39,7 @@ import (
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)

var (
Expand Down Expand Up @@ -143,10 +146,12 @@ func (b *testBackend) RunPeer(peer *Peer, handler Handler) error {
func (b *testBackend) PeerInfo(enode.ID) interface{} { panic("not implemented") }

func (b *testBackend) AcceptTxs() bool {
panic("data processing tests should be done in the handler package")
return true
//panic("data processing tests should be done in the handler package")
}
func (b *testBackend) Handle(*Peer, Packet) error {
panic("data processing tests should be done in the handler package")
return nil
//panic("data processing tests should be done in the handler package")
}

// Tests that block headers can be retrieved from a remote chain based on user queries.
Expand Down Expand Up @@ -499,3 +504,76 @@ func testGetBlockReceipts(t *testing.T, protocol uint) {
t.Errorf("receipts mismatch: %v", err)
}
}

type decoder struct {
msg []byte
}

func (d decoder) Decode(val interface{}) error {
buffer := bytes.NewBuffer(d.msg)
s := rlp.NewStream(buffer, uint64(len(d.msg)))
return s.Decode(val)
}

func (d decoder) Time() time.Time {
return time.Now()
}

func setup() (*testBackend, *testPeer) {
// Generate some transactions etc.
acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
Comment on lines +511 to +525

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

holiman sent new code style rules

acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey)
acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey)
signer := types.HomesteadSigner{}
gen := func(n int, block *core.BlockGen) {
if n%2 == 0 {
w := &types.Withdrawal{
Address: common.Address{0xaa},
Amount: 42,
}
block.AddWithdrawal(w)
}
switch n {
case 0:
// In block 1, the test bank sends account #1 some ether.
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(10_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey)
tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, acc1Key)
block.AddTx(tx1)
block.AddTx(tx2)
case 2:
// Block 3 is empty but was mined by account #2.
block.SetCoinbase(acc2Addr)
block.SetExtra([]byte("yeehaw"))
}
}
backend := newTestBackendWithGenerator(maxBodiesServe+15, true, gen)
peer, _ := newTestPeer("peer", ETH68, backend)
// Discard all messages
go func() {
for {
msg, err := peer.app.ReadMsg()
if err == nil {
msg.Discard()
}
}
}()
return backend, peer
}

func FuzzEthProtocolHandlers(f *testing.F) {
handlers := eth68
backend, peer := setup()
f.Fuzz(func(t *testing.T, code byte, msg []byte) {
handler := handlers[uint64(code)%protocolLengths[ETH68]]
if handler == nil {
return
}
handler(backend, decoder{msg: msg}, peer.Peer)
})
}
4 changes: 4 additions & 0 deletions oss-fuzz.sh
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/secp256k1 \
Fuzz fuzzSecp256k1\
$repo/tests/fuzzers/secp256k1/secp_test.go

compile_fuzzer github.com/ethereum/go-ethereum/eth/protocols/eth \
FuzzEthProtocolHandlers fuzz_eth_protocol_handlers \
$repo/eth/protocols/eth/handler_test.go


#compile_fuzzer tests/fuzzers/vflux FuzzClientPool fuzzClientPool
#compile_fuzzer tests/fuzzers/difficulty Fuzz fuzzDifficulty
Expand Down