Skip to content
Merged
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
4 changes: 2 additions & 2 deletions bench/rpc/cmd/corpus-gen/class_hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@
if err != nil {
return "", err
}
class, err := input.client.classAt(input.ctx, blockNumber, classHash)
isSierra, err := input.cache.isSierra(input.ctx, input.client, blockNumber, classHash)

Check warning on line 41 in bench/rpc/cmd/corpus-gen/class_hash.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/class_hash.go#L41

Added line #L41 was not covered by tests
if err != nil {
return "", err
}
if len(class.SierraProgram) == 0 {
if !isSierra {

Check warning on line 45 in bench/rpc/cmd/corpus-gen/class_hash.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/class_hash.go#L45

Added line #L45 was not covered by tests
return "", errResample
}
return classHash, nil
Expand Down
28 changes: 18 additions & 10 deletions bench/rpc/cmd/corpus-gen/get_storage_proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,28 +46,36 @@
// sampled trie members persist, so historical diffs are still valid sources.
params := storageProofParams{BlockID: "latest"}
for range input.args.NumClasses {
classHash, err := sampleSierraClassHash(input, input.args.sampleBlockNumber(input.rng))
// Cairo 0 hashes are fine here: keys absent from the classes trie
// yield valid non-membership proofs with near-identical node work.
classHash, err := resample(func() (string, error) {
return sampleClassHash(input, input.args.sampleBlockNumber(input.rng))
})

Check warning on line 53 in bench/rpc/cmd/corpus-gen/get_storage_proof.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/get_storage_proof.go#L51-L53

Added lines #L51 - L53 were not covered by tests
Comment thread
infrmtcs marked this conversation as resolved.
if err != nil {
return nil, err
return nil, fmt.Errorf("sample class hash: %w", err)

Check warning on line 55 in bench/rpc/cmd/corpus-gen/get_storage_proof.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/get_storage_proof.go#L55

Added line #L55 was not covered by tests
}
params.ClassHashes = append(params.ClassHashes, classHash)
}
for range input.args.NumContracts {
address, err := sampleContractAddress(
input,
input.args.sampleBlockNumber(input.rng),
storageDiffAddresses,
)
address, err := resample(func() (string, error) {
return sampleContractAddress(
input,
input.args.sampleBlockNumber(input.rng),
storageDiffAddresses,
)
})

Check warning on line 66 in bench/rpc/cmd/corpus-gen/get_storage_proof.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/get_storage_proof.go#L60-L66

Added lines #L60 - L66 were not covered by tests
if err != nil {
return nil, err
return nil, fmt.Errorf("sample contract address: %w", err)

Check warning on line 68 in bench/rpc/cmd/corpus-gen/get_storage_proof.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/get_storage_proof.go#L68

Added line #L68 was not covered by tests
}
params.ContractAddresses = append(params.ContractAddresses, address)
}
keyIndex := make(map[string]int)
for range input.args.NumKeys {
entry, err := sampleStorageEntry(input, input.args.sampleBlockNumber(input.rng))
entry, err := resample(func() (storageEntry, error) {
return sampleStorageEntry(input, input.args.sampleBlockNumber(input.rng))
})

Check warning on line 76 in bench/rpc/cmd/corpus-gen/get_storage_proof.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/get_storage_proof.go#L74-L76

Added lines #L74 - L76 were not covered by tests
if err != nil {
return nil, err
return nil, fmt.Errorf("sample storage key: %w", err)

Check warning on line 78 in bench/rpc/cmd/corpus-gen/get_storage_proof.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/get_storage_proof.go#L78

Added line #L78 was not covered by tests
}
if i, ok := keyIndex[entry.Address]; ok {
params.ContractsStorageKeys[i].StorageKeys = append(
Expand Down
41 changes: 38 additions & 3 deletions bench/rpc/cmd/corpus-gen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"math/rand/v2"
"os"
"runtime"
"sync"
"sync/atomic"
"time"

"github.com/sourcegraph/conc/pool"
Expand Down Expand Up @@ -166,7 +168,9 @@
) error {
generatedAt := time.Now().UTC().Format(time.RFC3339)

c, err := buildCorpus(cmd.Context(), cfg, client, method, meta, generatedAt, gen)
c, err := buildCorpus(
cmd.Context(), cfg, client, method, meta, generatedAt, gen, cmd.ErrOrStderr(),
)

Check warning on line 173 in bench/rpc/cmd/corpus-gen/main.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/main.go#L171-L173

Added lines #L171 - L173 were not covered by tests
if err != nil {
return err
}
Expand All @@ -187,12 +191,17 @@
meta T,
generatedAt string,
gen paramsGen,
progress io.Writer,
) (*corpus[T], error) {
version, err := client.specVersion(ctx)
if err != nil {
return nil, fmt.Errorf("fetch spec version: %w", err)
}

var completed atomic.Int64
stopProgress := reportProgress(progress, &completed, cfg.count)
defer stopProgress()

Check warning on line 203 in bench/rpc/cmd/corpus-gen/main.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/main.go#L201-L203

Added lines #L201 - L203 were not covered by tests

requests := make([]any, cfg.count)
p := pool.New().
WithContext(ctx).
Expand All @@ -215,9 +224,10 @@
}
if cfg.batch == 0 {
requests[i] = entry[0]
return nil
} else {
requests[i] = entry

Check warning on line 228 in bench/rpc/cmd/corpus-gen/main.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/main.go#L227-L228

Added lines #L227 - L228 were not covered by tests
}
requests[i] = entry
completed.Add(1)

Check warning on line 230 in bench/rpc/cmd/corpus-gen/main.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/main.go#L230

Added line #L230 was not covered by tests
return nil
})
}
Expand All @@ -239,6 +249,31 @@
}, nil
}

const progressInterval = 2 * time.Second

func reportProgress(w io.Writer, completed *atomic.Int64, total int) (stop func()) {
quit := make(chan struct{})
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
ticker := time.NewTicker(progressInterval)
defer ticker.Stop()
for {
select {
case <-quit:
return
case <-ticker.C:
fmt.Fprintf(w, "progress: %d/%d entries\n", completed.Load(), total)

Check warning on line 267 in bench/rpc/cmd/corpus-gen/main.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/main.go#L254-L267

Added lines #L254 - L267 were not covered by tests
}
}
}()
return func() {
close(quit)
wg.Wait()

Check warning on line 273 in bench/rpc/cmd/corpus-gen/main.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/main.go#L271-L273

Added lines #L271 - L273 were not covered by tests
}
}
Comment thread
infrmtcs marked this conversation as resolved.

func newSeededRand(seed, stream uint64) *rand.Rand {
//nolint:gosec // G404: deterministic corpus needs a seeded PRNG, not crypto randomness
return rand.New(rand.NewPCG(seed, stream))
Expand Down
33 changes: 23 additions & 10 deletions bench/rpc/cmd/corpus-gen/sampler.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
client *rpcClient
rng *rand.Rand
args *T
cache *sierraCache
}

type sampler[T any] func(input samplerInput[T]) (any, error)
Expand Down Expand Up @@ -54,32 +55,44 @@
return err
}
}
cache := newSierraCache()

Check warning on line 58 in bench/rpc/cmd/corpus-gen/sampler.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/sampler.go#L58

Added line #L58 was not covered by tests
gen := func(ctx context.Context, client *rpcClient, rng *rand.Rand) (any, error) {
input := samplerInput[T]{
ctx: ctx,
client: client,
rng: rng,
args: args,
cache: cache,

Check warning on line 65 in bench/rpc/cmd/corpus-gen/sampler.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/sampler.go#L65

Added line #L65 was not covered by tests
}
for range maxResampleAttempts {
result, err := sample(input)
if err == nil {
return result, nil
}
if !errors.Is(err, errResample) {
return nil, err
}
result, err := resample(func() (any, error) { return sample(input) })
if err != nil {
return nil, fmt.Errorf("%s: %w", method, err)

Check warning on line 69 in bench/rpc/cmd/corpus-gen/sampler.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/sampler.go#L67-L69

Added lines #L67 - L69 were not covered by tests
}
return nil, fmt.Errorf("%s: no candidate found after %d attempts", method, maxResampleAttempts)
return result, nil

Check warning on line 71 in bench/rpc/cmd/corpus-gen/sampler.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/sampler.go#L71

Added line #L71 was not covered by tests
}
return runCorpus(cmd, cfg, client, method, args, gen)
}
return cmd
}

// errResample tells newSampledCmd's loop to re-invoke the sampler.
// errResample tells resample to retry fn with fresh draws.
var errResample = errors.New("resample")

// resample retries fn until it succeeds or fails with a non-errResample error.
func resample[R any](fn func() (R, error)) (R, error) {
var zero R
for range maxResampleAttempts {
result, err := fn()
if err == nil {
return result, nil

Check warning on line 87 in bench/rpc/cmd/corpus-gen/sampler.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/sampler.go#L82-L87

Added lines #L82 - L87 were not covered by tests
}
if !errors.Is(err, errResample) {
return zero, err

Check warning on line 90 in bench/rpc/cmd/corpus-gen/sampler.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/sampler.go#L89-L90

Added lines #L89 - L90 were not covered by tests
}
}
return zero, fmt.Errorf("no candidate found after %d attempts", maxResampleAttempts)

Check warning on line 93 in bench/rpc/cmd/corpus-gen/sampler.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/sampler.go#L93

Added line #L93 was not covered by tests
}
Comment thread
infrmtcs marked this conversation as resolved.

func commandName(method string) string {
return strings.TrimPrefix(method, "starknet_")
}
Expand Down
58 changes: 58 additions & 0 deletions bench/rpc/cmd/corpus-gen/sierra_cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package main

import (
"context"
"sync"

"golang.org/x/sync/singleflight"
)

// sierraCache memoizes per class hash whether the class is Sierra, sparing
// repeat getClass downloads; a class's content is immutable, so verdicts
// never expire. Errors are not cached.
type sierraCache struct {
group singleflight.Group
mu sync.RWMutex
verdicts map[string]bool
}

func newSierraCache() *sierraCache {
return &sierraCache{verdicts: make(map[string]bool)}

Check warning on line 20 in bench/rpc/cmd/corpus-gen/sierra_cache.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/sierra_cache.go#L19-L20

Added lines #L19 - L20 were not covered by tests
}

func (c *sierraCache) isSierra(
ctx context.Context,
client *rpcClient,
blockNumber uint64,
classHash string,
) (bool, error) {
if verdict, ok := c.get(classHash); ok {
return verdict, nil

Check warning on line 30 in bench/rpc/cmd/corpus-gen/sierra_cache.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/sierra_cache.go#L28-L30

Added lines #L28 - L30 were not covered by tests
}
result, err, _ := c.group.Do(classHash, func() (any, error) {
class, err := client.classAt(ctx, blockNumber, classHash)
if err != nil {
return false, err

Check warning on line 35 in bench/rpc/cmd/corpus-gen/sierra_cache.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/sierra_cache.go#L32-L35

Added lines #L32 - L35 were not covered by tests
}
isSierra := len(class.SierraProgram) > 0
c.set(classHash, isSierra)
return isSierra, nil

Check warning on line 39 in bench/rpc/cmd/corpus-gen/sierra_cache.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/sierra_cache.go#L37-L39

Added lines #L37 - L39 were not covered by tests
})
if err != nil {
return false, err

Check warning on line 42 in bench/rpc/cmd/corpus-gen/sierra_cache.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/sierra_cache.go#L41-L42

Added lines #L41 - L42 were not covered by tests
}
return result.(bool), nil

Check warning on line 44 in bench/rpc/cmd/corpus-gen/sierra_cache.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/sierra_cache.go#L44

Added line #L44 was not covered by tests
}
Comment thread
infrmtcs marked this conversation as resolved.

func (c *sierraCache) get(classHash string) (verdict, ok bool) {
c.mu.RLock()
defer c.mu.RUnlock()
verdict, ok = c.verdicts[classHash]
return verdict, ok

Check warning on line 51 in bench/rpc/cmd/corpus-gen/sierra_cache.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/sierra_cache.go#L47-L51

Added lines #L47 - L51 were not covered by tests
}

func (c *sierraCache) set(classHash string, isSierra bool) {
c.mu.Lock()
defer c.mu.Unlock()
c.verdicts[classHash] = isSierra

Check warning on line 57 in bench/rpc/cmd/corpus-gen/sierra_cache.go

View check run for this annotation

Codecov / codecov/patch

bench/rpc/cmd/corpus-gen/sierra_cache.go#L54-L57

Added lines #L54 - L57 were not covered by tests
}
8 changes: 0 additions & 8 deletions bench/rpc/corpus/with_state_update.json

This file was deleted.

22 changes: 0 additions & 22 deletions bench/rpc/corpus/without_state_update.json

This file was deleted.

Loading