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

Add TBTC monitoring confirmations #592

Merged
merged 19 commits into from
Nov 12, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
3 changes: 3 additions & 0 deletions pkg/chain/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import (
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ipfs/go-log"
"github.com/keep-network/keep-common/pkg/subscription"
"github.com/keep-network/keep-core/pkg/chain"
"github.com/keep-network/keep-ecdsa/pkg/ecdsa"
)

var logger = log.Logger("keep-chain")

// Handle represents a handle to an ethereum blockchain.
type Handle interface {
// Address returns client's ethereum address.
Expand Down
32 changes: 32 additions & 0 deletions pkg/chain/confirmation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package eth

import (
"fmt"
)

// WaitForChainConfirmation ensures that after receiving specific number of block
// confirmations the state of the chain is actually as expected. It waits for
// predefined number of blocks since the start block number provided. After the
// required block number is reached it performs a check of the chain state with
// a provided function returning a boolean value.
func WaitForChainConfirmation(
pdyraga marked this conversation as resolved.
Show resolved Hide resolved
ethereumChain Handle,
startBlockNumber uint64,
blockConfirmations uint64,
stateCheck func() (bool, error),
) (bool, error) {
blockHeight := startBlockNumber + blockConfirmations
logger.Infof("waiting for block [%d] to confirm chain state", blockHeight)

err := ethereumChain.BlockCounter().WaitForBlockHeight(blockHeight)
if err != nil {
return false, fmt.Errorf("failed to wait for block height: [%v]", err)
}

result, err := stateCheck()
if err != nil {
return false, fmt.Errorf("failed to get chain state confirmation: [%v]", err)
}

return result, nil
}
17 changes: 17 additions & 0 deletions pkg/chain/ethereum/tbtc.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,23 @@ func (tec *TBTCEthereumChain) ProvideRedemptionProof(
return nil
}

// CurrentState returns the current state for the provided deposit.
func (tec *TBTCEthereumChain) CurrentState(
depositAddress string,
) (chain.DepositState, error) {
deposit, err := tec.getDepositContract(depositAddress)
if err != nil {
return 0, err
}

state, err := deposit.CurrentState()
if err != nil {
return 0, err
}

return chain.DepositState(state.Uint64()), err
}

func (tec *TBTCEthereumChain) getDepositContract(
address string,
) (*contract.Deposit, error) {
Expand Down
21 changes: 21 additions & 0 deletions pkg/chain/local/tbtc.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const (
type localDeposit struct {
keepAddress string
pubkey []byte
state chain.DepositState

utxoValue *big.Int
redemptionDigest [32]byte
Expand Down Expand Up @@ -114,6 +115,7 @@ func (tlc *TBTCLocalChain) CreateDeposit(depositAddress string) {

tlc.deposits[depositAddress] = &localDeposit{
keepAddress: keepAddress.Hex(),
state: chain.AwaitingSignerSetup,
utxoValue: big.NewInt(defaultUTXOValue),
redemptionRequestedEvents: make([]*chain.DepositRedemptionRequestedEvent, 0),
}
Expand Down Expand Up @@ -188,6 +190,7 @@ func (tlc *TBTCLocalChain) RedeemDeposit(depositAddress string) error {
return err
}

deposit.state = chain.AwaitingWithdrawalSignature
deposit.redemptionDigest = randomDigest
deposit.redemptionFee = big.NewInt(defaultInitialRedemptionFee)

Expand Down Expand Up @@ -346,6 +349,7 @@ func (tlc *TBTCLocalChain) RetrieveSignerPubkey(depositAddress string) error {
}

deposit.pubkey = keep.publicKey[:]
deposit.state = chain.AwaitingBtcFundingProof

for _, handler := range tlc.depositRegisteredPubkeyHandlers {
go func(handler func(depositAddress string), depositAddress string) {
Expand Down Expand Up @@ -387,6 +391,7 @@ func (tlc *TBTCLocalChain) ProvideRedemptionSignature(
)
}

deposit.state = chain.AwaitingWithdrawalProof
deposit.redemptionSignature = &Signature{
V: v,
R: r,
Expand Down Expand Up @@ -454,6 +459,7 @@ func (tlc *TBTCLocalChain) IncreaseRedemptionFee(
return err
}

deposit.state = chain.AwaitingWithdrawalSignature
deposit.redemptionDigest = randomDigest
deposit.redemptionFee = new(big.Int).Sub(deposit.utxoValue, newOutputValue)
deposit.redemptionSignature = nil
Expand Down Expand Up @@ -518,6 +524,7 @@ func (tlc *TBTCLocalChain) ProvideRedemptionProof(
)
}

deposit.state = chain.Redeemed
deposit.redemptionProof = &TxProof{}

for _, handler := range tlc.depositRedeemedHandlers {
Expand All @@ -529,6 +536,20 @@ func (tlc *TBTCLocalChain) ProvideRedemptionProof(
return nil
}

func (tlc *TBTCLocalChain) CurrentState(
depositAddress string,
) (chain.DepositState, error) {
tlc.mutex.Lock()
defer tlc.mutex.Unlock()

deposit, ok := tlc.deposits[depositAddress]
if !ok {
return 0, fmt.Errorf("no deposit with address [%v]", depositAddress)
}

return deposit.state, nil
}

func (tlc *TBTCLocalChain) DepositPubkey(
depositAddress string,
) ([]byte, error) {
Expand Down
21 changes: 21 additions & 0 deletions pkg/chain/tbtc.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ type Deposit interface {
txIndexInBlock *big.Int,
bitcoinHeaders []uint8,
) error

// CurrentState returns the current state for the provided deposit.
CurrentState(depositAddress string) (DepositState, error)
}

// TBTCSystem is an interface that provides ability to interact
Expand Down Expand Up @@ -112,3 +115,21 @@ type DepositRedemptionRequestedEvent struct {
Outpoint []byte
BlockNumber uint64
}

// DepositState represents the deposit state.
type DepositState int

const (
Start DepositState = iota
AwaitingSignerSetup
AwaitingBtcFundingProof
FailedSetup
Active
AwaitingWithdrawalSignature
AwaitingWithdrawalProof
Redeemed
CourtesyCall
FraudLiquidationInProgress
LiquidationInProgress
Liquidated
)
42 changes: 10 additions & 32 deletions pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package client

import (
"context"
"fmt"
"math/big"
"sync"
"time"
Expand Down Expand Up @@ -60,9 +59,10 @@ func Initialize(
return false
}

isKeepActive, err := waitForChainConfirmation(
isKeepActive, err := eth.WaitForChainConfirmation(
ethereumChain,
currentBlock,
blockConfirmations,
func() (bool, error) {
return ethereumChain.IsActive(keepAddress)
},
Expand Down Expand Up @@ -531,9 +531,10 @@ func monitorSigningRequests(
}
defer requestedSignatures.remove(keepAddress, event.Digest)

isAwaitingSignature, err := waitForChainConfirmation(
isAwaitingSignature, err := eth.WaitForChainConfirmation(
ethereumChain,
event.BlockNumber,
blockConfirmations,
func() (bool, error) {
return ethereumChain.IsAwaitingSignature(keepAddress, event.Digest)
},
Expand Down Expand Up @@ -618,9 +619,10 @@ func checkAwaitingSignature(
return
}

isStillAwaitingSignature, err := waitForChainConfirmation(
isStillAwaitingSignature, err := eth.WaitForChainConfirmation(
ethereumChain,
startBlock,
blockConfirmations,
func() (bool, error) {
isAwaitingSignature, err := ethereumChain.IsAwaitingSignature(keepAddress, latestDigest)
if err != nil {
Expand Down Expand Up @@ -704,9 +706,10 @@ func monitorKeepClosedEvents(
event.BlockNumber,
)

isKeepActive, err := waitForChainConfirmation(
isKeepActive, err := eth.WaitForChainConfirmation(
ethereumChain,
event.BlockNumber,
blockConfirmations,
func() (bool, error) {
return ethereumChain.IsActive(keepAddress)
},
Expand Down Expand Up @@ -767,9 +770,10 @@ func monitorKeepTerminatedEvent(
event.BlockNumber,
)

isKeepActive, err := waitForChainConfirmation(
isKeepActive, err := eth.WaitForChainConfirmation(
ethereumChain,
event.BlockNumber,
blockConfirmations,
func() (bool, error) {
return ethereumChain.IsActive(keepAddress)
},
Expand Down Expand Up @@ -809,29 +813,3 @@ func monitorKeepTerminatedEvent(

logger.Info("unsubscribing from events on keep terminated")
}

// waitForChainConfirmation ensures that after receiving specific number of block
// confirmations the state of the chain is actually as expected. It waits for
// predefined number of blocks since the start block number provided. After the
// required block number is reached it performs a check of the chain state with
// a provided function returning a boolean value.
func waitForChainConfirmation(
ethereumChain eth.Handle,
startBlockNumber uint64,
stateCheck func() (bool, error),
) (bool, error) {
blockHeight := startBlockNumber + blockConfirmations
logger.Infof("waiting for block [%d] to confirm chain state", blockHeight)

err := ethereumChain.BlockCounter().WaitForBlockHeight(blockHeight)
if err != nil {
return false, fmt.Errorf("failed to wait for block height: [%v]", err)
}

result, err := stateCheck()
if err != nil {
return false, fmt.Errorf("failed to get chain state confirmation: [%v]", err)
}

return result, nil
}
3 changes: 2 additions & 1 deletion pkg/client/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,10 @@ func monitorSignerPoolStatus(
)
}

isRegistered, err := waitForChainConfirmation(
isRegistered, err := eth.WaitForChainConfirmation(
ethereumChain,
statusCheckBlock,
blockConfirmations,
func() (bool, error) {
return ethereumChain.IsRegisteredForApplication(
application,
Expand Down
Loading