From ee32326c1af9906211d07d68790b6f702f44207f Mon Sep 17 00:00:00 2001 From: Lukasz Zimnoch Date: Wed, 24 Apr 2024 12:45:16 +0200 Subject: [PATCH] Cache swept deposits The current logic always fetches swept deposits from the chain using Ethereum RPC server. This can be optimized. Swept deposits are final and no further changes occur regarding their state. That means swept deposits can be cached. This allows reducing network load and speeding up processed that needs to check a large number of deposits (e.g. deposit sweep and moving funds proposal generators). We use a time cache to evict unused keys over time and optimize memory consumption. --- pkg/chain/ethereum/tbtc.go | 49 ++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/pkg/chain/ethereum/tbtc.go b/pkg/chain/ethereum/tbtc.go index 31f99f2e9d..b5b7a76a6c 100644 --- a/pkg/chain/ethereum/tbtc.go +++ b/pkg/chain/ethereum/tbtc.go @@ -5,6 +5,7 @@ import ( "crypto/elliptic" "encoding/binary" "fmt" + "github.com/keep-network/keep-common/pkg/cache" "math/big" "reflect" "sort" @@ -40,6 +41,10 @@ const ( WalletProposalValidatorContractName = "WalletProposalValidator" ) +const ( + sweptDepositsCachePeriod = 7 * 24 * time.Hour +) + // TbtcChain represents a TBTC-specific chain handle. type TbtcChain struct { *baseChain @@ -50,6 +55,8 @@ type TbtcChain struct { sortitionPool *ecdsacontract.EcdsaSortitionPool walletProposalValidator *tbtccontract.WalletProposalValidator redemptionWatchtower *tbtccontract.RedemptionWatchtower + + sweptDepositsCache *cache.GenericTimeCache[*tbtc.DepositChainRequest] } // NewTbtcChain construct a new instance of the TBTC-specific Ethereum @@ -237,6 +244,7 @@ func newTbtcChain( sortitionPool: sortitionPool, walletProposalValidator: walletProposalValidator, redemptionWatchtower: redemptionWatchtower, + sweptDepositsCache: cache.NewGenericTimeCache[*tbtc.DepositChainRequest](sweptDepositsCachePeriod), }, nil } @@ -1126,8 +1134,14 @@ func (tc *TbtcChain) GetDepositRequest( fundingOutputIndex uint32, ) (*tbtc.DepositChainRequest, bool, error) { depositKey := buildDepositKey(fundingTxHash, fundingOutputIndex) + depositCacheKey := depositKey.Text(16) + + tc.sweptDepositsCache.Sweep() + if cachedRequest, ok := tc.sweptDepositsCache.Get(depositCacheKey); ok { + return cachedRequest, true, nil + } - depositRequest, err := tc.bridge.Deposits(depositKey) + chainRequest, err := tc.bridge.Deposits(depositKey) if err != nil { return nil, false, fmt.Errorf( "cannot get deposit request for key [0x%x]: [%v]", @@ -1137,30 +1151,39 @@ func (tc *TbtcChain) GetDepositRequest( } // Deposit not found. - if depositRequest.RevealedAt == 0 { + if chainRequest.RevealedAt == 0 { return nil, false, nil } var vault *chain.Address - if depositRequest.Vault != [20]byte{} { - v := chain.Address(depositRequest.Vault.Hex()) + if chainRequest.Vault != [20]byte{} { + v := chain.Address(chainRequest.Vault.Hex()) vault = &v } var extraData *[32]byte - if depositRequest.ExtraData != [32]byte{} { - extraData = &depositRequest.ExtraData + if chainRequest.ExtraData != [32]byte{} { + extraData = &chainRequest.ExtraData } - return &tbtc.DepositChainRequest{ - Depositor: chain.Address(depositRequest.Depositor.Hex()), - Amount: depositRequest.Amount, - RevealedAt: time.Unix(int64(depositRequest.RevealedAt), 0), + request := &tbtc.DepositChainRequest{ + Depositor: chain.Address(chainRequest.Depositor.Hex()), + Amount: chainRequest.Amount, + RevealedAt: time.Unix(int64(chainRequest.RevealedAt), 0), Vault: vault, - TreasuryFee: depositRequest.TreasuryFee, - SweptAt: time.Unix(int64(depositRequest.SweptAt), 0), + TreasuryFee: chainRequest.TreasuryFee, + SweptAt: time.Unix(int64(chainRequest.SweptAt), 0), ExtraData: extraData, - }, true, nil + } + + // If the request was swept on-chain, there is a guarantee that no + // further changes will occur regarding its parameters. + // Such a request can be cached. + if isSwept := request.SweptAt.Unix() != 0; isSwept { + tc.sweptDepositsCache.Add(depositCacheKey, request) + } + + return request, true, nil } func (tc *TbtcChain) PastNewWalletRegisteredEvents(