Skip to content

Commit 84ef55e

Browse files
committed
Optimize RPC requests
1 parent 785c6ab commit 84ef55e

File tree

2 files changed

+78
-8
lines changed

2 files changed

+78
-8
lines changed

go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,7 @@ github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09
504504
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
505505
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
506506
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
507+
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
507508
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
508509
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
509510
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=

storage/remote/store.go

Lines changed: 77 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"strconv"
2626
"strings"
2727

28+
lru "github.com/hashicorp/golang-lru/v2"
2829
"github.com/onflow/flow-go/engine/common/rpc/convert"
2930
"github.com/onflow/flow-go/fvm/environment"
3031
"github.com/onflow/flow-go/fvm/errors"
@@ -276,7 +277,18 @@ func (s *Store) LedgerByHeight(
276277
ctx context.Context,
277278
blockHeight uint64,
278279
) (snapshot.StorageSnapshot, error) {
280+
// Create a snapshot with LRU cache to avoid duplicate RPC calls within the same snapshot
281+
// LRU cache with max 1000 entries to prevent memory bloat
282+
cache, err := lru.New[string, flowgo.RegisterValue](1000)
283+
if err != nil {
284+
return nil, fmt.Errorf("failed to create LRU cache: %w", err)
285+
}
286+
279287
return snapshot.NewReadFuncStorageSnapshot(func(id flowgo.RegisterID) (flowgo.RegisterValue, error) {
288+
// Check LRU cache first to avoid duplicate RPC calls within this snapshot
289+
if cachedValue, exists := cache.Get(id.String()); exists {
290+
return cachedValue, nil
291+
}
280292
// create a copy so updating it doesn't affect future calls
281293
lookupHeight := blockHeight
282294

@@ -378,6 +390,8 @@ func (s *Store) LedgerByHeight(
378390
return nil, fmt.Errorf("could not cache ledger value: %w", err)
379391
}
380392

393+
// Cache in LRU cache for this snapshot to avoid duplicate RPC calls
394+
cache.Add(id.String(), value)
381395
return value, nil
382396
}), nil
383397
}
@@ -458,6 +472,40 @@ func (s *Store) fetchRemoteRegister(ctx context.Context, owner string, key strin
458472
return nil, nil
459473
}
460474

475+
// COMPATIBILITY SHIM: Batch register fetching to reduce RPC calls
476+
// TODO: Remove after Flow release - batches multiple register lookups into single RPC call
477+
func (s *Store) fetchRemoteRegisters(ctx context.Context, owner string, keys []string, height uint64) (map[string][]byte, error) {
478+
if len(keys) == 0 {
479+
return make(map[string][]byte), nil
480+
}
481+
482+
registerIDs := make([]*entities.RegisterID, len(keys))
483+
for i, key := range keys {
484+
registerIDs[i] = convert.RegisterIDToMessage(flowgo.RegisterID{Key: key, Owner: owner})
485+
}
486+
487+
response, err := s.executionClient.GetRegisterValues(ctx, &executiondata.GetRegisterValuesRequest{
488+
BlockHeight: height,
489+
RegisterIds: registerIDs,
490+
})
491+
if err != nil {
492+
if status.Code(err) == codes.NotFound {
493+
return make(map[string][]byte), nil
494+
}
495+
return nil, err
496+
}
497+
498+
result := make(map[string][]byte)
499+
if response != nil && len(response.Values) > 0 {
500+
for i, key := range keys {
501+
if i < len(response.Values) && len(response.Values[i]) > 0 {
502+
result[key] = response.Values[i]
503+
}
504+
}
505+
}
506+
return result, nil
507+
}
508+
461509
// COMPATIBILITY SHIM: Batch public key synthesis
462510
// TODO: Remove after Flow release - builds batch public key payloads from individual public_key_* registers
463511
func (s *Store) synthesizeBatchPublicKeys(ctx context.Context, owner string, batchIndex uint32, height uint64) ([]byte, error) {
@@ -496,16 +544,28 @@ func (s *Store) synthesizeBatchPublicKeys(ctx context.Context, owner string, bat
496544
batch = append(batch, 0x00)
497545
}
498546

547+
// Batch fetch all legacy public key registers for this batch to reduce RPC calls
548+
legacyKeys := make([]string, 0, end-start+1)
549+
for i := start; i <= end; i++ {
550+
if i == 0 {
551+
continue // skip key 0
552+
}
553+
legacyKeys = append(legacyKeys, fmt.Sprintf("public_key_%d", i))
554+
}
555+
556+
legacyValues, err := s.fetchRemoteRegisters(ctx, owner, legacyKeys, height)
557+
if err != nil {
558+
return nil, err
559+
}
560+
499561
for i := start; i <= end; i++ {
500562
if i == 0 {
501563
// stored key 0 is apk_0 and not included in batch payload (nil placeholder already added)
502564
continue
503565
}
504566
legacyKey := fmt.Sprintf("public_key_%d", i)
505-
legacyVal, err := s.fetchRemoteRegister(ctx, owner, legacyKey, height)
506-
if err != nil {
507-
return nil, err
508-
}
567+
legacyVal := legacyValues[legacyKey]
568+
509569
if len(legacyVal) == 0 {
510570
// keep index alignment with zero-length entry
511571
batch = append(batch, 0x00)
@@ -628,15 +688,24 @@ func (s *Store) buildKeyMetadataFromLegacy(ctx context.Context, owner string, co
628688
return nil, nil
629689
}
630690

691+
// Batch fetch all legacy public key registers to reduce RPC calls
692+
legacyKeys := make([]string, count-1)
693+
for i := uint32(1); i < count; i++ {
694+
legacyKeys[i-1] = fmt.Sprintf("public_key_%d", i)
695+
}
696+
697+
legacyValues, err := s.fetchRemoteRegisters(ctx, owner, legacyKeys, height)
698+
if err != nil {
699+
return nil, err
700+
}
701+
631702
// Build weight and revoked status for keys 1..count-1
632703
var weightAndRevoked []byte
633704

634705
for i := uint32(1); i < count; i++ {
635706
legacyKey := fmt.Sprintf("public_key_%d", i)
636-
legacyVal, err := s.fetchRemoteRegister(ctx, owner, legacyKey, height)
637-
if err != nil {
638-
return nil, err
639-
}
707+
legacyVal := legacyValues[legacyKey]
708+
640709
if len(legacyVal) == 0 {
641710
// Default values for missing keys
642711
weightAndRevoked = append(weightAndRevoked, 0, 0) // weight=0, revoked=false

0 commit comments

Comments
 (0)