Skip to content
This repository has been archived by the owner on May 22, 2023. It is now read-only.

TBTC extension optimizations #600

Merged
merged 8 commits into from
Nov 13, 2020
Merged
Show file tree
Hide file tree
Changes from 6 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
122 changes: 103 additions & 19 deletions pkg/extensions/tbtc/tbtc.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"sync"
"time"

"github.com/keep-network/keep-common/pkg/cache"

"github.com/ethereum/go-ethereum/common"

"github.com/ipfs/go-log"
Expand All @@ -24,9 +26,24 @@ import (
var logger = log.Logger("tbtc-extension")

const (
maxActAttempts = 3
pastEventsLookbackBlocks = 10000
// Maximum number of action attempts before giving up and returning
// a monitoring error.
maxActAttempts = 3

// Determines how many blocks from the past should be included
// during the past events lookup.
pastEventsLookbackBlocks = 10000

// Number of blocks which should elapse before confirming
// the given chain state expectations.
defaultBlockConfirmations = 12

// Determines how long the monitoring cache will maintain
// its entries.
pdyraga marked this conversation as resolved.
Show resolved Hide resolved
monitoringCachePeriod = 24 * time.Hour

// Used to calculate the action delay factor for the given signer index.
pdyraga marked this conversation as resolved.
Show resolved Hide resolved
defaultSignerActionDelayStep = 5 * time.Minute
)

// TODO: Resume monitoring after client restart
Expand Down Expand Up @@ -80,15 +97,21 @@ func Initialize(ctx context.Context, chain chain.TBTCHandle) error {
}

type tbtc struct {
chain chain.TBTCHandle
monitoringLocks sync.Map
blockConfirmations uint64
chain chain.TBTCHandle
monitoringLocks sync.Map
blockConfirmations uint64
monitoredDepositsCache *cache.TimeCache
notMonitoredDepositsCache *cache.TimeCache
signerActionDelayStep time.Duration
}

func newTBTC(chain chain.TBTCHandle) *tbtc {
return &tbtc{
chain: chain,
blockConfirmations: defaultBlockConfirmations,
chain: chain,
blockConfirmations: defaultBlockConfirmations,
monitoredDepositsCache: cache.NewTimeCache(monitoringCachePeriod),
notMonitoredDepositsCache: cache.NewTimeCache(monitoringCachePeriod),
signerActionDelayStep: defaultSignerActionDelayStep,
}
}

Expand Down Expand Up @@ -141,6 +164,15 @@ func (t *tbtc) monitorRetrievePubKey(
return nil
}

timeoutFn := func(depositAddress string) (time.Duration, error) {
actionDelay, err := t.getSignerActionDelay(depositAddress)
if err != nil {
return 0, err
}

return timeout + actionDelay, nil
}

monitoringSubscription, err := t.monitorAndAct(
ctx,
"retrieve pubkey",
Expand All @@ -150,9 +182,7 @@ func (t *tbtc) monitorRetrievePubKey(
t.watchKeepClosed,
actFn,
actBackoffFn,
func(_ string) (time.Duration, error) {
return timeout, nil
},
timeoutFn,
)
if err != nil {
return err
Expand Down Expand Up @@ -313,6 +343,15 @@ func (t *tbtc) monitorProvideRedemptionSignature(
return nil
}

timeoutFn := func(depositAddress string) (time.Duration, error) {
actionDelay, err := t.getSignerActionDelay(depositAddress)
if err != nil {
return 0, err
}

return timeout + actionDelay, nil
}

monitoringSubscription, err := t.monitorAndAct(
ctx,
"provide redemption signature",
Expand All @@ -322,9 +361,7 @@ func (t *tbtc) monitorProvideRedemptionSignature(
t.watchKeepClosed,
actFn,
actBackoffFn,
func(_ string) (time.Duration, error) {
return timeout, nil
},
timeoutFn,
)
if err != nil {
return err
Expand Down Expand Up @@ -502,7 +539,12 @@ func (t *tbtc) monitorProvideRedemptionProof(
gotRedemptionSignatureTimestamp-redemptionRequestedTimestamp,
) * time.Second

return timeout - timeoutShift, nil
actionDelay, err := t.getSignerActionDelay(depositAddress)
if err != nil {
return 0, err
}

return (timeout - timeoutShift) + actionDelay, nil
}

monitoringSubscription, err := t.monitorAndAct(
Expand Down Expand Up @@ -761,23 +803,65 @@ func (t *tbtc) watchKeepClosed(
}

func (t *tbtc) shouldMonitorDeposit(depositAddress string) bool {
pdyraga marked this conversation as resolved.
Show resolved Hide resolved
pdyraga marked this conversation as resolved.
Show resolved Hide resolved
keepAddress, err := t.chain.KeepAddress(depositAddress)
t.monitoredDepositsCache.Sweep()
t.notMonitoredDepositsCache.Sweep()

if t.monitoredDepositsCache.Has(depositAddress) {
return true
}

if t.notMonitoredDepositsCache.Has(depositAddress) {
return false
}

signerIndex, err := t.getSignerIndex(depositAddress)
if err != nil {
logger.Errorf(
"could not get signer index for deposit [%v]: [%v]",
depositAddress,
err,
)
return false // return false but don't cache the result in case of error
pdyraga marked this conversation as resolved.
Show resolved Hide resolved
}

if signerIndex < 0 {
t.notMonitoredDepositsCache.Add(depositAddress)
return false
}

t.monitoredDepositsCache.Add(depositAddress)
return true
}

func (t *tbtc) getSignerIndex(depositAddress string) (int, error) {
keepAddress, err := t.chain.KeepAddress(depositAddress)
if err != nil {
return -1, err
}

members, err := t.chain.GetMembers(common.HexToAddress(keepAddress))
if err != nil {
return false
return -1, err
}

for _, member := range members {
for index, member := range members {
if member == t.chain.Address() {
return true
return index, nil
}
}

return false
return -1, nil
}

func (t *tbtc) getSignerActionDelay(
pdyraga marked this conversation as resolved.
Show resolved Hide resolved
depositAddress string,
) (time.Duration, error) {
signerIndex, err := t.getSignerIndex(depositAddress)
if err != nil {
return 0, err
}

return time.Duration(signerIndex) * t.signerActionDelayStep, nil
}

func (t *tbtc) waitDepositStateChangeConfirmation(
Expand Down
Loading