Skip to content

Commit

Permalink
Unit tests for wallet maintainer redemptions (#3668)
Browse files Browse the repository at this point in the history
Here we add missing unit tests for the wallet maintainer redemption
code.
  • Loading branch information
pdyraga authored Jul 5, 2023
2 parents ff030d5 + 3c3d046 commit d117a44
Show file tree
Hide file tree
Showing 10 changed files with 1,112 additions and 51 deletions.
306 changes: 298 additions & 8 deletions pkg/maintainer/wallet/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package wallet

import (
"bytes"
"context"
"crypto/sha256"
"encoding/binary"
"encoding/hex"
Expand All @@ -27,6 +28,16 @@ type depositParameters = struct {
revealAheadPeriod uint32
}

type redemptionParameters = struct {
dustThreshold uint64
treasuryFeeDivisor uint64
txMaxFee uint64
txMaxTotalFee uint64
timeout uint32
timeoutSlashingAmount *big.Int
timeoutNotifierRewardMultiplier uint32
}

type LocalChain struct {
mutex sync.Mutex

Expand All @@ -37,6 +48,14 @@ type LocalChain struct {
depositSweepProposalValidations map[[32]byte]bool
depositSweepProposals []*tbtc.DepositSweepProposal
walletLocks map[[20]byte]*walletLock
redemptionParameters redemptionParameters
redemptionRequestMinAge uint32
blockCounter chain.BlockCounter
pastRedemptionRequestedEvents map[[32]byte][]*tbtc.RedemptionRequestedEvent
averageBlockTime time.Duration
pendingRedemptionRequests map[[32]byte]*tbtc.RedemptionRequest
redemptionProposals []*tbtc.RedemptionProposal
redemptionProposalValidations map[[32]byte]bool
}

func NewLocalChain() *LocalChain {
Expand All @@ -46,6 +65,9 @@ func NewLocalChain() *LocalChain {
pastNewWalletRegisteredEvents: make(map[[32]byte][]*tbtc.NewWalletRegisteredEvent),
depositSweepProposalValidations: make(map[[32]byte]bool),
walletLocks: make(map[[20]byte]*walletLock),
pastRedemptionRequestedEvents: make(map[[32]byte][]*tbtc.RedemptionRequestedEvent),
pendingRedemptionRequests: make(map[[32]byte]*tbtc.RedemptionRequest),
redemptionProposalValidations: make(map[[32]byte]bool),
}
}

Expand All @@ -56,6 +78,13 @@ func (lc *LocalChain) DepositSweepProposals() []*tbtc.DepositSweepProposal {
return lc.depositSweepProposals
}

func (lc *LocalChain) RedemptionProposals() []*tbtc.RedemptionProposal {
lc.mutex.Lock()
defer lc.mutex.Unlock()

return lc.redemptionProposals
}

func (lc *LocalChain) PastDepositRevealedEvents(
filter *tbtc.DepositRevealedEventFilter,
) ([]*tbtc.DepositRevealedEvent, error) {
Expand Down Expand Up @@ -236,7 +265,75 @@ func buildPastNewWalletRegisteredEventsKey(
func (lc *LocalChain) PastRedemptionRequestedEvents(
filter *tbtc.RedemptionRequestedEventFilter,
) ([]*tbtc.RedemptionRequestedEvent, error) {
panic("unsupported")
lc.mutex.Lock()
defer lc.mutex.Unlock()

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

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

return events, nil
}

func (lc *LocalChain) AddPastRedemptionRequestedEvent(
filter *tbtc.RedemptionRequestedEventFilter,
event *tbtc.RedemptionRequestedEvent,
) error {
lc.mutex.Lock()
defer lc.mutex.Unlock()

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

lc.pastRedemptionRequestedEvents[eventsKey] = append(
lc.pastRedemptionRequestedEvents[eventsKey],
event,
)

return nil
}

func buildPastRedemptionRequestedEventsKey(
filter *tbtc.RedemptionRequestedEventFilter,
) ([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[:])
}

for _, redeemer := range filter.Redeemer {
redeemerHex, err := hex.DecodeString(redeemer.String())
if err != nil {
return [32]byte{}, err
}

buffer.Write(redeemerHex)
}

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

func (lc *LocalChain) BuildDepositKey(fundingTxHash bitcoin.Hash, fundingOutputIndex uint32) *big.Int {
Expand All @@ -259,7 +356,19 @@ func (lc *LocalChain) BuildRedemptionKey(
walletPublicKeyHash [20]byte,
redeemerOutputScript bitcoin.Script,
) (*big.Int, error) {
panic("unsupported")
redemptionKeyBytes := buildRedemptionRequestKey(
walletPublicKeyHash,
redeemerOutputScript,
)

return new(big.Int).SetBytes(redemptionKeyBytes[:]), nil
}

func buildRedemptionRequestKey(
walletPublicKeyHash [20]byte,
redeemerOutputScript bitcoin.Script,
) [32]byte {
return sha256.Sum256(append(walletPublicKeyHash[:], redeemerOutputScript...))
}

func (lc *LocalChain) GetDepositParameters() (
Expand All @@ -283,7 +392,32 @@ func (lc *LocalChain) GetPendingRedemptionRequest(
walletPublicKeyHash [20]byte,
redeemerOutputScript bitcoin.Script,
) (*tbtc.RedemptionRequest, error) {
panic("unsupported")
lc.mutex.Lock()
defer lc.mutex.Unlock()

requestKey := buildRedemptionRequestKey(walletPublicKeyHash, redeemerOutputScript)

request, ok := lc.pendingRedemptionRequests[requestKey]
if !ok {
return nil, fmt.Errorf("not request for given key")
}

return request, nil
}

func (lc *LocalChain) SetPendingRedemptionRequest(
walletPublicKeyHash [20]byte,
request *tbtc.RedemptionRequest,
) {
lc.mutex.Lock()
defer lc.mutex.Unlock()

requestKey := buildRedemptionRequestKey(
walletPublicKeyHash,
request.RedeemerOutputScript,
)

lc.pendingRedemptionRequests[requestKey] = request
}

func (lc *LocalChain) SetDepositParameters(
Expand Down Expand Up @@ -313,7 +447,40 @@ func (lc *LocalChain) GetRedemptionParameters() (
timeoutNotifierRewardMultiplier uint32,
err error,
) {
panic("unsupported")
lc.mutex.Lock()
defer lc.mutex.Unlock()

return lc.redemptionParameters.dustThreshold,
lc.redemptionParameters.treasuryFeeDivisor,
lc.redemptionParameters.txMaxFee,
lc.redemptionParameters.txMaxTotalFee,
lc.redemptionParameters.timeout,
lc.redemptionParameters.timeoutSlashingAmount,
lc.redemptionParameters.timeoutNotifierRewardMultiplier,
nil
}

func (lc *LocalChain) SetRedemptionParameters(
dustThreshold uint64,
treasuryFeeDivisor uint64,
txMaxFee uint64,
txMaxTotalFee uint64,
timeout uint32,
timeoutSlashingAmount *big.Int,
timeoutNotifierRewardMultiplier uint32,
) {
lc.mutex.Lock()
defer lc.mutex.Unlock()

lc.redemptionParameters = redemptionParameters{
dustThreshold: dustThreshold,
treasuryFeeDivisor: treasuryFeeDivisor,
txMaxFee: txMaxFee,
txMaxTotalFee: txMaxTotalFee,
timeout: timeout,
timeoutSlashingAmount: timeoutSlashingAmount,
timeoutNotifierRewardMultiplier: timeoutNotifierRewardMultiplier,
}
}

func (lc *LocalChain) ValidateDepositSweepProposal(
Expand Down Expand Up @@ -398,21 +565,86 @@ func (lc *LocalChain) SubmitDepositSweepProposalWithReimbursement(
func (lc *LocalChain) SubmitRedemptionProposalWithReimbursement(
proposal *tbtc.RedemptionProposal,
) error {
panic("unsupported")
lc.mutex.Lock()
defer lc.mutex.Unlock()

lc.redemptionProposals = append(lc.redemptionProposals, proposal)

return nil
}

func (lc *LocalChain) ValidateRedemptionProposal(
proposal *tbtc.RedemptionProposal,
) error {
panic("unsupported")
lc.mutex.Lock()
defer lc.mutex.Unlock()

key, err := buildRedemptionProposalValidationKey(proposal)
if err != nil {
return err
}

result, ok := lc.redemptionProposalValidations[key]
if !ok {
return fmt.Errorf("validation result unknown")
}

if !result {
return fmt.Errorf("validation failed")
}

return nil
}

func (lc *LocalChain) SetRedemptionProposalValidationResult(
proposal *tbtc.RedemptionProposal,
result bool,
) error {
lc.mutex.Lock()
defer lc.mutex.Unlock()

key, err := buildRedemptionProposalValidationKey(proposal)
if err != nil {
return err
}

lc.redemptionProposalValidations[key] = result

return nil
}

func buildRedemptionProposalValidationKey(
proposal *tbtc.RedemptionProposal,
) ([32]byte, error) {
var buffer bytes.Buffer

buffer.Write(proposal.WalletPublicKeyHash[:])

for _, script := range proposal.RedeemersOutputScripts {
buffer.Write(script)
}

buffer.Write(proposal.RedemptionTxFee.Bytes())

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

func (lc *LocalChain) GetRedemptionMaxSize() (uint16, error) {
panic("unsupported")
}

func (lc *LocalChain) GetRedemptionRequestMinAge() (uint32, error) {
panic("unsupported")
lc.mutex.Lock()
defer lc.mutex.Unlock()

return lc.redemptionRequestMinAge, nil
}

func (lc *LocalChain) SetRedemptionRequestMinAge(redemptionRequestMinAge uint32) {
lc.mutex.Lock()
defer lc.mutex.Unlock()

lc.redemptionRequestMinAge = redemptionRequestMinAge
}

func (lc *LocalChain) GetDepositSweepMaxSize() (uint16, error) {
Expand Down Expand Up @@ -460,9 +692,67 @@ func (lc *LocalChain) ResetWalletLock(
}

func (lc *LocalChain) BlockCounter() (chain.BlockCounter, error) {
panic("unsupported")
lc.mutex.Lock()
defer lc.mutex.Unlock()

return lc.blockCounter, nil
}

func (lc *LocalChain) SetBlockCounter(blockCounter chain.BlockCounter) {
lc.mutex.Lock()
defer lc.mutex.Unlock()

lc.blockCounter = blockCounter
}

func (lc *LocalChain) AverageBlockTime() time.Duration {
lc.mutex.Lock()
defer lc.mutex.Unlock()

return lc.averageBlockTime
}

func (lc *LocalChain) SetAverageBlockTime(averageBlockTime time.Duration) {
lc.mutex.Lock()
defer lc.mutex.Unlock()

lc.averageBlockTime = averageBlockTime
}

type MockBlockCounter struct {
mutex sync.Mutex
currentBlock uint64
}

func NewMockBlockCounter() *MockBlockCounter {
return &MockBlockCounter{}
}

func (mbc *MockBlockCounter) WaitForBlockHeight(blockNumber uint64) error {
panic("unsupported")
}

func (mbc *MockBlockCounter) BlockHeightWaiter(blockNumber uint64) (
<-chan uint64,
error,
) {
panic("unsupported")
}

func (mbc *MockBlockCounter) CurrentBlock() (uint64, error) {
mbc.mutex.Lock()
defer mbc.mutex.Unlock()

return mbc.currentBlock, nil
}

func (mbc *MockBlockCounter) SetCurrentBlock(block uint64) {
mbc.mutex.Lock()
defer mbc.mutex.Unlock()

mbc.currentBlock = block
}

func (mbc *MockBlockCounter) WatchBlocks(ctx context.Context) <-chan uint64 {
panic("unsupported")
}
Loading

0 comments on commit d117a44

Please sign in to comment.