Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Harden moving funds against edge cases #3813

Merged
merged 7 commits into from
May 6, 2024
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
26 changes: 26 additions & 0 deletions pkg/tbtc/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,32 @@ type BridgeChain interface {
movingFundsTxHash bitcoin.Hash,
movingFundsTxOutpointIndex uint32,
) (*MovedFundsSweepRequest, bool, error)

// GetMovingFundsParameters gets the current value of parameters relevant
// for the moving funds process.
GetMovingFundsParameters() (
txMaxTotalFee uint64,
dustThreshold uint64,
timeoutResetDelay uint32,
timeout uint32,
timeoutSlashingAmount *big.Int,
timeoutNotifierRewardMultiplier uint32,
commitmentGasOffset uint16,
sweepTxMaxTotalFee uint64,
sweepTimeout uint32,
sweepTimeoutSlashingAmount *big.Int,
sweepTimeoutNotifierRewardMultiplier uint32,
err error,
)

// PastMovingFundsCommitmentSubmittedEvents fetches past moving funds
// commitment submitted events according to the provided filter or
// unfiltered if the filter is nil. Returned events are sorted by the block
// number in the ascending order, i.e. the latest event is at the end of the
// slice.
PastMovingFundsCommitmentSubmittedEvents(
filter *MovingFundsCommitmentSubmittedEventFilter,
) ([]*MovingFundsCommitmentSubmittedEvent, error)
}

// NewWalletRegisteredEvent represents a new wallet registered event.
Expand Down
171 changes: 158 additions & 13 deletions pkg/tbtc/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,20 @@ import (

const localChainOperatorID = chain.OperatorID(1)

type movingFundsParameters = struct {
txMaxTotalFee uint64
dustThreshold uint64
timeoutResetDelay uint32
timeout uint32
timeoutSlashingAmount *big.Int
timeoutNotifierRewardMultiplier uint32
commitmentGasOffset uint16
sweepTxMaxTotalFee uint64
sweepTimeout uint32
sweepTimeoutSlashingAmount *big.Int
sweepTimeoutNotifierRewardMultiplier uint32
}

type localChain struct {
dkgResultSubmissionHandlersMutex sync.Mutex
dkgResultSubmissionHandlers map[int]func(submission *DKGResultSubmittedEvent)
Expand Down Expand Up @@ -57,6 +71,9 @@ type localChain struct {
pastDepositRevealedEventsMutex sync.Mutex
pastDepositRevealedEvents map[[32]byte][]*DepositRevealedEvent

pastMovingFundsCommitmentSubmittedEventsMutex sync.Mutex
pastMovingFundsCommitmentSubmittedEvents map[[32]byte][]*MovingFundsCommitmentSubmittedEvent

depositSweepProposalValidationsMutex sync.Mutex
depositSweepProposalValidations map[[32]byte]bool

Expand All @@ -81,6 +98,9 @@ type localChain struct {
depositRequestsMutex sync.Mutex
depositRequests map[[32]byte]*DepositChainRequest

movingFundsParametersMutex sync.Mutex
movingFundsParameters movingFundsParameters

blockCounter chain.BlockCounter
operatorPrivateKey *operator.PrivateKey
}
Expand Down Expand Up @@ -1099,6 +1119,130 @@ func buildMovedFundsSweepProposalValidationKey(
return sha256.Sum256(buffer.Bytes()), nil
}

func (lc *localChain) GetMovingFundsParameters() (
txMaxTotalFee uint64,
dustThreshold uint64,
timeoutResetDelay uint32,
timeout uint32,
timeoutSlashingAmount *big.Int,
timeoutNotifierRewardMultiplier uint32,
commitmentGasOffset uint16,
sweepTxMaxTotalFee uint64,
sweepTimeout uint32,
sweepTimeoutSlashingAmount *big.Int,
sweepTimeoutNotifierRewardMultiplier uint32,
err error,
) {
lc.movingFundsParametersMutex.Lock()
defer lc.movingFundsParametersMutex.Unlock()

return lc.movingFundsParameters.txMaxTotalFee,
lc.movingFundsParameters.dustThreshold,
lc.movingFundsParameters.timeoutResetDelay,
lc.movingFundsParameters.timeout,
lc.movingFundsParameters.timeoutSlashingAmount,
lc.movingFundsParameters.timeoutNotifierRewardMultiplier,
lc.movingFundsParameters.commitmentGasOffset,
lc.movingFundsParameters.sweepTxMaxTotalFee,
lc.movingFundsParameters.sweepTimeout,
lc.movingFundsParameters.sweepTimeoutSlashingAmount,
lc.movingFundsParameters.sweepTimeoutNotifierRewardMultiplier,
nil
}

func (lc *localChain) SetMovingFundsParameters(
txMaxTotalFee uint64,
dustThreshold uint64,
timeoutResetDelay uint32,
timeout uint32,
timeoutSlashingAmount *big.Int,
timeoutNotifierRewardMultiplier uint32,
commitmentGasOffset uint16,
sweepTxMaxTotalFee uint64,
sweepTimeout uint32,
sweepTimeoutSlashingAmount *big.Int,
sweepTimeoutNotifierRewardMultiplier uint32,
) {
lc.movingFundsParametersMutex.Lock()
defer lc.movingFundsParametersMutex.Unlock()

lc.movingFundsParameters = movingFundsParameters{
txMaxTotalFee: txMaxTotalFee,
dustThreshold: dustThreshold,
timeoutResetDelay: timeoutResetDelay,
timeout: timeout,
timeoutSlashingAmount: timeoutSlashingAmount,
timeoutNotifierRewardMultiplier: timeoutNotifierRewardMultiplier,
commitmentGasOffset: commitmentGasOffset,
sweepTxMaxTotalFee: sweepTxMaxTotalFee,
sweepTimeout: sweepTimeout,
sweepTimeoutSlashingAmount: sweepTimeoutSlashingAmount,
sweepTimeoutNotifierRewardMultiplier: sweepTimeoutNotifierRewardMultiplier,
}
}

func (lc *localChain) PastMovingFundsCommitmentSubmittedEvents(
filter *MovingFundsCommitmentSubmittedEventFilter,
) ([]*MovingFundsCommitmentSubmittedEvent, error) {
lc.pastMovingFundsCommitmentSubmittedEventsMutex.Lock()
defer lc.pastMovingFundsCommitmentSubmittedEventsMutex.Unlock()

eventsKey, err := buildPastMovingFundsCommitmentSubmittedEventsKey(filter)
if err != nil {
return nil, err
}

events, ok := lc.pastMovingFundsCommitmentSubmittedEvents[eventsKey]
if !ok {
return nil, fmt.Errorf("no events for given filter")
}

return events, nil
}

func (lc *localChain) setPastMovingFundsCommitmentSubmittedEvents(
filter *MovingFundsCommitmentSubmittedEventFilter,
events []*MovingFundsCommitmentSubmittedEvent,
) error {
lc.pastMovingFundsCommitmentSubmittedEventsMutex.Lock()
defer lc.pastMovingFundsCommitmentSubmittedEventsMutex.Unlock()

eventsKey, err := buildPastMovingFundsCommitmentSubmittedEventsKey(filter)
if err != nil {
return err
}

lc.pastMovingFundsCommitmentSubmittedEvents[eventsKey] = events

return nil
}

func buildPastMovingFundsCommitmentSubmittedEventsKey(
filter *MovingFundsCommitmentSubmittedEventFilter,
) ([32]byte, error) {
if filter == nil {
return [32]byte{}, nil
}

var buffer bytes.Buffer

startBlock := make([]byte, 8)
binary.BigEndian.PutUint64(startBlock, filter.StartBlock)
buffer.Write(startBlock)

if filter.EndBlock != nil {
endBlock := make([]byte, 8)
binary.BigEndian.PutUint64(startBlock, *filter.EndBlock)
buffer.Write(endBlock)
}

for _, walletPublicKeyHash := range filter.WalletPublicKeyHash {
buffer.Write(walletPublicKeyHash[:])
}

return sha256.Sum256(buffer.Bytes()), nil
}

// Connect sets up the local chain.
func Connect(blockTime ...time.Duration) *localChain {
operatorPrivateKey, _, err := operator.GenerateKeyPair(local_v1.DefaultCurve)
Expand Down Expand Up @@ -1127,19 +1271,20 @@ func ConnectWithKey(
dkgResultChallengeHandlers: make(
map[int]func(submission *DKGResultChallengedEvent),
),
wallets: make(map[[20]byte]*WalletChainData),
blocksByTimestamp: make(map[uint64]uint64),
blocksHashesByNumber: make(map[uint64][32]byte),
pastDepositRevealedEvents: make(map[[32]byte][]*DepositRevealedEvent),
depositSweepProposalValidations: make(map[[32]byte]bool),
pendingRedemptionRequests: make(map[[32]byte]*RedemptionRequest),
redemptionProposalValidations: make(map[[32]byte]bool),
movingFundsProposalValidations: make(map[[32]byte]bool),
movedFundsSweepProposalValidations: make(map[[32]byte]bool),
heartbeatProposalValidations: make(map[[16]byte]bool),
depositRequests: make(map[[32]byte]*DepositChainRequest),
blockCounter: blockCounter,
operatorPrivateKey: operatorPrivateKey,
wallets: make(map[[20]byte]*WalletChainData),
blocksByTimestamp: make(map[uint64]uint64),
blocksHashesByNumber: make(map[uint64][32]byte),
pastDepositRevealedEvents: make(map[[32]byte][]*DepositRevealedEvent),
pastMovingFundsCommitmentSubmittedEvents: make(map[[32]byte][]*MovingFundsCommitmentSubmittedEvent),
depositSweepProposalValidations: make(map[[32]byte]bool),
pendingRedemptionRequests: make(map[[32]byte]*RedemptionRequest),
redemptionProposalValidations: make(map[[32]byte]bool),
movingFundsProposalValidations: make(map[[32]byte]bool),
movedFundsSweepProposalValidations: make(map[[32]byte]bool),
heartbeatProposalValidations: make(map[[16]byte]bool),
depositRequests: make(map[[32]byte]*DepositChainRequest),
blockCounter: blockCounter,
operatorPrivateKey: operatorPrivateKey,
}

return localChain
Expand Down
Loading
Loading