mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-19 00:54:12 +00:00
help fuzzer
This commit is contained in:
parent
aef904971c
commit
730cd96e9b
@ -4,7 +4,9 @@
|
|||||||
package txpool
|
package txpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/btree"
|
"github.com/google/btree"
|
||||||
@ -83,7 +85,7 @@ func FuzzTwoQueue(f *testing.F) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func u64Slice(in []byte) ([]uint64, bool) {
|
func u64Slice(in []byte) ([]uint64, bool) {
|
||||||
if len(in)%8 != 0 {
|
if len(in) < 8 {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
res := make([]uint64, len(in)/8)
|
res := make([]uint64, len(in)/8)
|
||||||
@ -93,7 +95,7 @@ func u64Slice(in []byte) ([]uint64, bool) {
|
|||||||
return res, true
|
return res, true
|
||||||
}
|
}
|
||||||
func u256Slice(in []byte) ([]uint256.Int, bool) {
|
func u256Slice(in []byte) ([]uint256.Int, bool) {
|
||||||
if len(in)%32 != 0 {
|
if len(in) < 32 {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
res := make([]uint256.Int, len(in)/32)
|
res := make([]uint256.Int, len(in)/32)
|
||||||
@ -103,32 +105,26 @@ func u256Slice(in []byte) ([]uint256.Int, bool) {
|
|||||||
return res, true
|
return res, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func poolsFromFuzzBytes(rawTxNonce, rawValues, rawTips, rawSender, rawSenderNonce, rawSenderBalance []byte) (sendersInfo map[uint64]*senderInfo, senderIDs map[string]uint64, txs TxSlots, ok bool) {
|
func parseSenders(rawSenders []byte) (senders Addresses, nonces []uint64, balances []uint256.Int) {
|
||||||
if len(rawTxNonce) < 8 || len(rawValues) < 32 || len(rawTips) < 8 || len(rawSender) < 20 || len(rawSenderNonce) < 8 || len(rawSenderBalance) < 32 {
|
for i := 0; i < len(rawSenders)-(20+8+32-1); i += 20 + 8 + 32 {
|
||||||
return nil, nil, txs, false
|
senders = append(senders, rawSenders[i:i+20]...)
|
||||||
}
|
nonce := binary.BigEndian.Uint64(rawSenders[i+20:])
|
||||||
if len(rawTxNonce) != len(rawTips) {
|
if nonce == 0 {
|
||||||
return nil, nil, txs, false
|
nonce = 1
|
||||||
}
|
|
||||||
if len(rawTxNonce)*32/8 != len(rawValues) {
|
|
||||||
return nil, nil, txs, false
|
|
||||||
}
|
|
||||||
if len(rawSenderNonce)*20/8 != len(rawSender) {
|
|
||||||
return nil, nil, txs, false
|
|
||||||
}
|
|
||||||
if len(rawSenderNonce)*32/8 != len(rawSenderBalance) {
|
|
||||||
return nil, nil, txs, false
|
|
||||||
}
|
|
||||||
senderNonce, ok := u64Slice(rawSenderNonce)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, txs, false
|
|
||||||
}
|
|
||||||
for i := 0; i < len(senderNonce); i++ {
|
|
||||||
if senderNonce[i] == 0 {
|
|
||||||
return nil, nil, txs, false
|
|
||||||
}
|
}
|
||||||
|
nonces = append(nonces, nonce)
|
||||||
|
balance := uint256.NewInt(0)
|
||||||
|
balance.SetBytes(rawSenders[i+20+8 : i+20+8+32])
|
||||||
|
balances = append(balances, *balance)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func poolsFromFuzzBytes(rawTxNonce, rawValues, rawTips, rawSender []byte) (sendersInfo map[uint64]*senderInfo, senderIDs map[string]uint64, txs TxSlots, ok bool) {
|
||||||
|
if len(rawTxNonce) < 8 || len(rawValues) < 32 || len(rawTips) < 8 || len(rawSender) < 20+8+32 {
|
||||||
|
return nil, nil, txs, false
|
||||||
|
}
|
||||||
|
senders, senderNonce, senderBalance := parseSenders(rawSender)
|
||||||
txNonce, ok := u64Slice(rawTxNonce)
|
txNonce, ok := u64Slice(rawTxNonce)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, nil, txs, false
|
return nil, nil, txs, false
|
||||||
@ -141,27 +137,21 @@ func poolsFromFuzzBytes(rawTxNonce, rawValues, rawTips, rawSender, rawSenderNonc
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil, nil, txs, false
|
return nil, nil, txs, false
|
||||||
}
|
}
|
||||||
senderBalance, ok := u256Slice(rawSenderBalance)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, txs, false
|
|
||||||
}
|
|
||||||
|
|
||||||
sendersInfo = map[uint64]*senderInfo{}
|
sendersInfo = map[uint64]*senderInfo{}
|
||||||
senderIDs = map[string]uint64{}
|
senderIDs = map[string]uint64{}
|
||||||
for i := 0; i < len(senderNonce); i++ {
|
for i := 0; i < len(senderNonce); i++ {
|
||||||
senderID := uint64(i + 1) //non-zero expected
|
senderID := uint64(i + 1) //non-zero expected
|
||||||
sendersInfo[senderID] = newSenderInfo(senderNonce[i], senderBalance[i])
|
sendersInfo[senderID] = newSenderInfo(senderNonce[i], senderBalance[i%len(senderBalance)])
|
||||||
senderIDs[string(rawSender[i*20:(i+1)*20])] = senderID
|
senderIDs[string(senders.At(i%senders.Len()))] = senderID
|
||||||
}
|
}
|
||||||
sendersAmount := len(sendersInfo)
|
|
||||||
for i := range txNonce {
|
for i := range txNonce {
|
||||||
txs.txs = append(txs.txs, &TxSlot{
|
txs.txs = append(txs.txs, &TxSlot{
|
||||||
nonce: txNonce[i],
|
nonce: txNonce[i],
|
||||||
value: values[i],
|
value: values[i%len(values)],
|
||||||
tip: tips[i],
|
tip: tips[i%len(tips)],
|
||||||
})
|
})
|
||||||
senderN := i % sendersAmount
|
txs.senders = append(txs.senders, senders.At(i%senders.Len())...)
|
||||||
txs.senders = append(txs.senders, rawSender[senderN*20:(senderN+1)*20]...)
|
|
||||||
txs.isLocal = append(txs.isLocal, false)
|
txs.isLocal = append(txs.isLocal, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,25 +187,26 @@ func splitDataset(in TxSlots) (TxSlots, TxSlots, TxSlots, TxSlots) {
|
|||||||
return p1, p2, p3, p4
|
return p1, p2, p3, p4
|
||||||
}
|
}
|
||||||
|
|
||||||
func FuzzOnNewBlocks6(f *testing.F) {
|
func FuzzOnNewBlocks7(f *testing.F) {
|
||||||
var u64 = [8 * 4]byte{1}
|
var u64 = [8 * 4]byte{1}
|
||||||
var u256 = [32 * 4]byte{1}
|
var sender = [20 + 8 + 32]byte{1}
|
||||||
f.Add(u64[:], u64[:], u64[:], u64[:], u256[:], u256[:], 123, 456)
|
f.Add(u64[:], u64[:], u64[:], sender[:], 123, 456)
|
||||||
f.Add(u64[:], u64[:], u64[:], u64[:], u256[:], u256[:], 78, 100)
|
f.Add(u64[:], u64[:], u64[:], sender[:], 78, 100)
|
||||||
f.Add(u64[:], u64[:], u64[:], u64[:], u256[:], u256[:], 100_000, 101_000)
|
f.Add(u64[:], u64[:], u64[:], sender[:], 100_000, 101_000)
|
||||||
f.Fuzz(func(t *testing.T, txNonce, values, tips, sender, senderNonce, senderBalance []byte, protocolBaseFee, blockBaseFee uint64) {
|
f.Fuzz(func(t *testing.T, txNonce, values, tips, sender []byte, protocolBaseFee, blockBaseFee uint64) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
if protocolBaseFee == 0 || blockBaseFee == 0 {
|
if protocolBaseFee == 0 || blockBaseFee == 0 {
|
||||||
t.Skip()
|
t.Skip()
|
||||||
}
|
}
|
||||||
if len(txNonce)%(8*4) != 0 || len(txNonce) != len(tips) {
|
if len(sender) < 20+8+32 {
|
||||||
t.Skip()
|
t.Skip()
|
||||||
}
|
}
|
||||||
|
|
||||||
senders, senderIDs, txs, ok := poolsFromFuzzBytes(txNonce, values, tips, sender, senderNonce, senderBalance)
|
senders, senderIDs, txs, ok := poolsFromFuzzBytes(txNonce, values, tips, sender)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Skip()
|
t.Skip()
|
||||||
}
|
}
|
||||||
|
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
err := txs.Valid()
|
err := txs.Valid()
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
@ -226,6 +217,9 @@ func FuzzOnNewBlocks6(f *testing.F) {
|
|||||||
pool.senderIDs = senderIDs
|
pool.senderIDs = senderIDs
|
||||||
check := func(unwindTxs, minedTxs TxSlots) {
|
check := func(unwindTxs, minedTxs TxSlots) {
|
||||||
pending, baseFee, queued := pool.pending, pool.baseFee, pool.queued
|
pending, baseFee, queued := pool.pending, pool.baseFee, pool.queued
|
||||||
|
if pending.Len() > 0 || baseFee.Len() > 0 || queued.Len() > 0 {
|
||||||
|
fmt.Printf("len: %d,%d,%d\n", pending.Len(), baseFee.Len(), queued.Len())
|
||||||
|
}
|
||||||
|
|
||||||
best, worst := pending.Best(), pending.Worst()
|
best, worst := pending.Best(), pending.Worst()
|
||||||
assert.LessOrEqual(pending.Len(), PendingSubPoolLimit)
|
assert.LessOrEqual(pending.Len(), PendingSubPoolLimit)
|
||||||
@ -333,39 +327,54 @@ func FuzzOnNewBlocks6(f *testing.F) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkNotify := func(unwindTxs, minedTxs TxSlots) {
|
||||||
|
select {
|
||||||
|
case newHashes := <-ch:
|
||||||
|
//assert.Equal(len(unwindTxs.txs), newHashes.Len())
|
||||||
|
assert.Greater(len(newHashes), 0)
|
||||||
|
for i := 0; i < newHashes.Len(); i++ {
|
||||||
|
foundInUnwind := false
|
||||||
|
foundInMined := false
|
||||||
|
newHash := newHashes.At(i)
|
||||||
|
for j := range unwindTxs.txs {
|
||||||
|
if bytes.Equal(unwindTxs.txs[j].idHash[:], newHash) {
|
||||||
|
foundInUnwind = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for j := range minedTxs.txs {
|
||||||
|
if bytes.Equal(unwindTxs.txs[j].idHash[:], newHash) {
|
||||||
|
foundInMined = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.True(foundInUnwind)
|
||||||
|
assert.False(foundInMined)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
|
||||||
|
//TODO: no notifications - means pools must be empty (unchanged)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// go to first fork
|
// go to first fork
|
||||||
unwindTxs, minedTxs1, p2pReceived, minedTxs2 := splitDataset(txs)
|
unwindTxs, minedTxs1, p2pReceived, minedTxs2 := splitDataset(txs)
|
||||||
err = pool.OnNewBlock(unwindTxs, minedTxs1, protocolBaseFee, blockBaseFee)
|
err = pool.OnNewBlock(unwindTxs, minedTxs1, protocolBaseFee, blockBaseFee)
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
check(unwindTxs, minedTxs1)
|
check(unwindTxs, minedTxs1)
|
||||||
select {
|
checkNotify(unwindTxs, minedTxs1)
|
||||||
case newHashes := <-ch:
|
|
||||||
assert.Greater(len(newHashes), 0)
|
|
||||||
//TODO: all notified hashes must be in given list
|
|
||||||
default:
|
|
||||||
//TODO: no notifications - means pools must be empty (unchanged)
|
|
||||||
}
|
|
||||||
//assert.Equal(len(unwindTxs.txs), newHashes.Len())
|
|
||||||
|
|
||||||
// unwind everything and switch to new fork (need unwind mined now)
|
// unwind everything and switch to new fork (need unwind mined now)
|
||||||
err = pool.OnNewBlock(minedTxs1, minedTxs2, protocolBaseFee, blockBaseFee)
|
err = pool.OnNewBlock(minedTxs1, minedTxs2, protocolBaseFee, blockBaseFee)
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
check(minedTxs1, minedTxs2)
|
check(minedTxs1, minedTxs2)
|
||||||
select {
|
checkNotify(minedTxs1, minedTxs2)
|
||||||
case newHashes := <-ch:
|
|
||||||
assert.Greater(len(newHashes), 0)
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
// add some remote txs from p2p
|
// add some remote txs from p2p
|
||||||
err = pool.OnNewTxs(p2pReceived)
|
err = pool.OnNewTxs(p2pReceived)
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
check(TxSlots{}, p2pReceived)
|
check(p2pReceived, TxSlots{})
|
||||||
select {
|
checkNotify(p2pReceived, TxSlots{})
|
||||||
case newHashes := <-ch:
|
|
||||||
assert.Greater(len(newHashes), 0)
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user