From 8ca2c0cef41983f26124310fd5a97e791e791993 Mon Sep 17 00:00:00 2001 From: "alex.sharov" Date: Thu, 29 Jul 2021 15:23:17 +0700 Subject: [PATCH] fuzz example --- txpool/pool.go | 88 ++++++++++++++++++++++++++++++++++++++++ txpool/pool_fuzz.go | 28 ------------- txpool/pool_fuzz_test.go | 59 +++++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 28 deletions(-) delete mode 100644 txpool/pool_fuzz.go create mode 100644 txpool/pool_fuzz_test.go diff --git a/txpool/pool.go b/txpool/pool.go index 02b6c4345..29a785e2a 100644 --- a/txpool/pool.go +++ b/txpool/pool.go @@ -261,6 +261,94 @@ func PromoteStep(pending, baseFee, queued *SubPool) { } } +func CheckInvariants(pending, baseFee, queued *SubPool) { + //1. If top element in the worst green queue has SubPool != 0b1111 (binary), it needs to be removed from the green pool. + // If SubPool < 0b1000 (not satisfying minimum fee), discard. + // If SubPool == 0b1110, demote to the yellow pool, otherwise demote to the red pool. + for worst := pending.Worst(); pending.Len() > 0; worst = pending.Worst() { + if worst.SubPool >= 0b11110 { + break + } + if worst.SubPool >= 0b11100 { + baseFee.Add(pending.PopWorst()) + continue + } + if worst.SubPool >= 0b11000 { + queued.Add(pending.PopWorst()) + continue + } + pending.PopWorst() + } + + //2. If top element in the worst green queue has SubPool == 0b1111, but there is not enough room in the pool, discard. + for worst := pending.Worst(); pending.Len() > PendingSubPoolLimit; worst = pending.Worst() { + if worst.SubPool >= 0b11110 { // TODO: here must 'SubPool == 0b1111' or 'SubPool <= 0b1111' ? + break + } + pending.PopWorst() + } + + //3. If the top element in the best yellow queue has SubPool == 0b1111, promote to the green pool. + for best := baseFee.Best(); baseFee.Len() > 0; best = baseFee.Best() { + if best.SubPool < 0b11110 { + break + } + pending.Add(baseFee.PopWorst()) + } + + //4. If the top element in the worst yellow queue has SubPool != 0x1110, it needs to be removed from the yellow pool. + // If SubPool < 0b1000 (not satisfying minimum fee), discard. Otherwise, demote to the red pool. + for worst := baseFee.Worst(); baseFee.Len() > 0; worst = baseFee.Worst() { + if worst.SubPool >= 0b11100 { + break + } + if worst.SubPool >= 0b11000 { + queued.Add(baseFee.PopWorst()) + continue + } + baseFee.PopWorst() + } + + //5. If the top element in the worst yellow queue has SubPool == 0x1110, but there is not enough room in the pool, discard. + for worst := baseFee.Worst(); baseFee.Len() > BaseFeeSubPoolLimit; worst = baseFee.Worst() { + if worst.SubPool >= 0b11110 { + break + } + baseFee.PopWorst() + } + + //6. If the top element in the best red queue has SubPool == 0x1110, promote to the yellow pool. If SubPool == 0x1111, promote to the green pool. + for best := queued.Best(); queued.Len() > 0; best = queued.Best() { + if best.SubPool < 0b11100 { + break + } + if best.SubPool < 0b11110 { + baseFee.Add(queued.PopWorst()) + continue + } + + pending.Add(queued.PopWorst()) + } + + //7. If the top element in the worst red queue has SubPool < 0b1000 (not satisfying minimum fee), discard. + for worst := queued.Worst(); queued.Len() > 0; worst = queued.Worst() { + if worst.SubPool >= 0b10000 { + break + } + + queued.PopWorst() + } + + //8. If the top element in the worst red queue has SubPool >= 0b100, but there is not enough room in the pool, discard. + for worst := queued.Worst(); queued.Len() > QueuedSubPoolLimit; worst = queued.Worst() { + if worst.SubPool >= 0b10000 { + break + } + + queued.PopWorst() + } +} + // Below is a draft code, will convert it to Loop and LoopStep funcs later type PoolImpl struct { diff --git a/txpool/pool_fuzz.go b/txpool/pool_fuzz.go deleted file mode 100644 index 9cb551179..000000000 --- a/txpool/pool_fuzz.go +++ /dev/null @@ -1,28 +0,0 @@ -// +build gofuzzbeta - -package txpool - -// https://blog.golang.org/fuzz-beta -// golang.org/s/draft-fuzzing-design -//gotip doc testing -//gotip doc testing.F -//gotip doc testing.F.Add -//gotip doc testing.F.Fuzz - -func FuzzParseQuery(f *testing.F) { - f.Add("x=1&y=2") - f.Fuzz(func(t *testing.T, queryStr string) { - query, err := url.ParseQuery(queryStr) - if err != nil { - t.Skip() - } - queryStr2 := query.Encode() - query2, err := url.ParseQuery(queryStr2) - if err != nil { - t.Fatalf("ParseQuery failed to decode a valid encoded query %s: %v", queryStr2, err) - } - if !reflect.DeepEqual(query, query2) { - t.Errorf("ParseQuery gave different query after being encoded\nbefore: %v\nafter: %v", query, query2) - } - }) -} diff --git a/txpool/pool_fuzz_test.go b/txpool/pool_fuzz_test.go new file mode 100644 index 000000000..f88a31414 --- /dev/null +++ b/txpool/pool_fuzz_test.go @@ -0,0 +1,59 @@ +// +build gofuzzbeta + +package txpool + +import ( + "testing" +) + +// https://blog.golang.org/fuzz-beta +// golang.org/s/draft-fuzzing-design +//gotip doc testing +//gotip doc testing.F +//gotip doc testing.F.Add +//gotip doc testing.F.Fuzz + +//func FuzzParseQuery(f *testing.F) { +// f.Add("x=1&y=2") +// f.Fuzz(func(t *testing.T, queryStr string) { +// query, err := url.ParseQuery(queryStr) +// if err != nil { +// t.Skip() +// } +// queryStr2 := query.Encode() +// query2, err := url.ParseQuery(queryStr2) +// if err != nil { +// t.Fatalf("ParseQuery failed to decode a valid encoded query %s: %v", queryStr2, err) +// } +// if !reflect.DeepEqual(query, query2) { +// t.Errorf("ParseQuery gave different query after being encoded\nbefore: %v\nafter: %v", query, query2) +// } +// }) +//} + +func FuzzPromoteStep(f *testing.F) { + f.Add([]uint8{0b11111, 0b10001, 0b10101, 0b00001, 0b00000}, []uint8{0b11111, 0b10001, 0b10101, 0b00001, 0b00000}, []uint8{0b11111, 0b10001, 0b10101, 0b00001, 0b00000}) + f.Fuzz(func(t *testing.T, s1, s2, s3 []uint8) { + t.Parallel() + pending := NewSubPool() + for i := range s1 { + s1[i] &= 0b11111 + pending.Add(&MetaTx{SubPool: SubPoolMarker(s1[i])}) + } + baseFee := NewSubPool() + for i := range s2 { + s2[i] &= 0b11111 + baseFee.Add(&MetaTx{SubPool: SubPoolMarker(s2[i])}) + } + queue := NewSubPool() + for i := range s3 { + s3[i] &= 0b11111 + queue.Add(&MetaTx{SubPool: SubPoolMarker(s3[i])}) + } + PromoteStep(pending, baseFee, queue) + + if pending.Best() != nil && pending.Best().SubPool < 0b11110 { + t.Fatalf("Pending best too small %b", pending.Best().SubPool) + } + }) +}