Skip to content

Commit

Permalink
Merge branch 'dev' into fix-bab-10
Browse files Browse the repository at this point in the history
  • Loading branch information
gitferry committed Apr 4, 2024
2 parents 4ffc885 + 5592229 commit ec25892
Show file tree
Hide file tree
Showing 14 changed files with 291 additions and 167 deletions.
29 changes: 15 additions & 14 deletions clientcontroller/babylon.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import (
"github.com/btcsuite/btcd/btcec/v2"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

bbnclient "github.com/babylonchain/babylon/client/client"
bbntypes "github.com/babylonchain/babylon/types"
btcctypes "github.com/babylonchain/babylon/x/btccheckpoint/types"
btclctypes "github.com/babylonchain/babylon/x/btclightclient/types"
btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types"
bbnclient "github.com/babylonchain/rpc-client/client"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg"
sdkclient "github.com/cosmos/cosmos-sdk/client"
Expand Down Expand Up @@ -91,17 +91,17 @@ func (bc *BabylonController) GetKeyAddress() sdk.AccAddress {
return addr
}

func (bc *BabylonController) QueryStakingParams() (*types.StakingParams, error) {
func (bc *BabylonController) QueryStakingParamsByVersion(version uint32) (*types.StakingParams, error) {
// query btc checkpoint params
ckptParamRes, err := bc.bbnClient.QueryClient.BTCCheckpointParams()
if err != nil {
return nil, fmt.Errorf("failed to query params of the btccheckpoint module: %v", err)
}

// query btc staking params
stakingParamRes, err := bc.bbnClient.QueryClient.BTCStakingParams()
stakingParamRes, err := bc.bbnClient.QueryClient.BTCStakingParamsByVersion(version)
if err != nil {
return nil, fmt.Errorf("failed to query staking params: %v", err)
return nil, fmt.Errorf("failed to query staking params with version %d: %v", version, err)
}

covenantPks := make([]*btcec.PublicKey, 0, len(stakingParamRes.Params.CovenantPks))
Expand Down Expand Up @@ -249,16 +249,17 @@ func DelegationRespToDelegation(del *btcstakingtypes.BTCDelegationResponse) (*ty
}

return &types.Delegation{
BtcPk: del.BtcPk.MustToBTCPK(),
FpBtcPks: fpBtcPks,
TotalSat: del.TotalSat,
StartHeight: del.StartHeight,
EndHeight: del.EndHeight,
StakingTxHex: del.StakingTxHex,
SlashingTxHex: del.SlashingTxHex,
CovenantSigs: covenantSigs,
UnbondingTime: del.UnbondingTime,
BtcUndelegation: undelegation,
BtcPk: del.BtcPk.MustToBTCPK(),
FpBtcPks: fpBtcPks,
TotalSat: del.TotalSat,
StartHeight: del.StartHeight,
EndHeight: del.EndHeight,
StakingTxHex: del.StakingTxHex,
SlashingTxHex: del.SlashingTxHex,
StakingOutputIdx: del.StakingOutputIdx,
CovenantSigs: covenantSigs,
UnbondingTime: del.UnbondingTime,
BtcUndelegation: undelegation,
}, nil
}

Expand Down
3 changes: 2 additions & 1 deletion clientcontroller/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package clientcontroller

import (
"fmt"

"github.com/btcsuite/btcd/chaincfg"
"go.uber.org/zap"

Expand All @@ -22,7 +23,7 @@ type ClientController interface {
// QueryPendingDelegations queries BTC delegations that are in status of pending
QueryPendingDelegations(limit uint64) ([]*types.Delegation, error)

QueryStakingParams() (*types.StakingParams, error)
QueryStakingParamsByVersion(version uint32) (*types.StakingParams, error)

Close() error
}
Expand Down
2 changes: 1 addition & 1 deletion config/babylon.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package config
import (
"time"

bbncfg "github.com/babylonchain/rpc-client/config"
bbncfg "github.com/babylonchain/babylon/client/config"
)

type BBNConfig struct {
Expand Down
73 changes: 29 additions & 44 deletions covenant/covenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,21 @@ import (
"sync"
"time"

"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/wire"

"github.com/avast/retry-go/v4"
"github.com/btcsuite/btcd/btcec/v2"

"go.uber.org/zap"

covcfg "github.com/babylonchain/covenant-emulator/config"
"github.com/babylonchain/covenant-emulator/keyring"

"github.com/babylonchain/babylon/btcstaking"
asig "github.com/babylonchain/babylon/crypto/schnorr-adaptor-signature"
bbntypes "github.com/babylonchain/babylon/types"
bstypes "github.com/babylonchain/babylon/x/btcstaking/types"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/wire"
"go.uber.org/zap"

"github.com/babylonchain/covenant-emulator/clientcontroller"
covcfg "github.com/babylonchain/covenant-emulator/config"
"github.com/babylonchain/covenant-emulator/keyring"
"github.com/babylonchain/covenant-emulator/types"
)

Expand All @@ -51,7 +47,6 @@ type CovenantEmulator struct {
kc *keyring.ChainKeyringController

config *covcfg.Config
params *types.StakingParams
logger *zap.Logger

// input is used to pass passphrase to the keyring
Expand Down Expand Up @@ -111,16 +106,6 @@ func (ce *CovenantEmulator) PublicKeyStr() string {
return hex.EncodeToString(schnorr.SerializePubKey(ce.pk))
}

func (ce *CovenantEmulator) UpdateParams() error {
params, err := ce.getParamsWithRetry()
if err != nil {
return err
}
ce.params = params

return nil
}

// AddCovenantSignatures adds Covenant signatures on every given Bitcoin delegations and submits them
// in a batch to Babylon. Invalid delegations will be skipped with error log error will be returned if
// the batch submission fails
Expand All @@ -142,22 +127,28 @@ func (ce *CovenantEmulator) AddCovenantSignatures(btcDels []*types.Delegation) (
continue
}

// 1. the quorum is already achieved, skip sending more sigs
// 1. get the params matched to the delegation version
params, err := ce.getParamsByVersionWithRetry(btcDel.ParamsVersion)
if err != nil {
return nil, fmt.Errorf("failed to get staking params with version %d: %w", btcDel.ParamsVersion, err)
}

// 2. the quorum is already achieved, skip sending more sigs
stakerPkHex := hex.EncodeToString(schnorr.SerializePubKey(btcDel.BtcPk))
if btcDel.HasCovenantQuorum(ce.params.CovenantQuorum) {
if btcDel.HasCovenantQuorum(params.CovenantQuorum) {
ce.logger.Error("covenant signatures already fulfilled",
zap.String("staker_pk", stakerPkHex),
zap.String("staking_tx_hex", btcDel.StakingTxHex),
)
continue
}

// 2. check unbonding time (staking time from unbonding tx) is larger than min unbonding time
// 3. check unbonding time (staking time from unbonding tx) is larger than min unbonding time
// which is larger value from:
// - MinUnbondingTime
// - CheckpointFinalizationTimeout
unbondingTime := btcDel.UnbondingTime
minUnbondingTime := ce.params.MinUnbondingTime
minUnbondingTime := params.MinUnbondingTime
if unbondingTime <= minUnbondingTime {
ce.logger.Error("invalid unbonding time",
zap.Uint32("min_unbonding_time", minUnbondingTime),
Expand All @@ -166,8 +157,8 @@ func (ce *CovenantEmulator) AddCovenantSignatures(btcDels []*types.Delegation) (
continue
}

// 3. decode staking tx and slashing tx from the delegation
stakingTx, slashingTx, err := decodeDelegationTransactions(btcDel, ce.params, &ce.config.BTCNetParams)
// 4. decode staking tx and slashing tx from the delegation
stakingTx, slashingTx, err := decodeDelegationTransactions(btcDel, params, &ce.config.BTCNetParams)
if err != nil {
ce.logger.Error("invalid delegation",
zap.String("staker_pk", stakerPkHex),
Expand All @@ -178,8 +169,8 @@ func (ce *CovenantEmulator) AddCovenantSignatures(btcDels []*types.Delegation) (
continue
}

// 4. decode unbonding tx and slash unbonding tx from the undelegation
unbondingTx, slashUnbondingTx, err := decodeUndelegationTransactions(btcDel, ce.params, &ce.config.BTCNetParams)
// 5. decode unbonding tx and slash unbonding tx from the undelegation
unbondingTx, slashUnbondingTx, err := decodeUndelegationTransactions(btcDel, params, &ce.config.BTCNetParams)
if err != nil {
ce.logger.Error("invalid undelegation",
zap.String("staker_pk", stakerPkHex),
Expand All @@ -190,7 +181,7 @@ func (ce *CovenantEmulator) AddCovenantSignatures(btcDels []*types.Delegation) (
continue
}

// 5. sign covenant staking sigs
// 6. sign covenant staking sigs
// record metrics
startSignTime := time.Now()
metricsTimeKeeper.SetPreviousSignStart(&startSignTime)
Expand All @@ -206,21 +197,21 @@ func (ce *CovenantEmulator) AddCovenantSignatures(btcDels []*types.Delegation) (
slashingTx,
unbondingTx,
covenantPrivKey,
ce.params,
params,
&ce.config.BTCNetParams,
)
if err != nil {
ce.logger.Error("failed to sign signatures or unbonding signature", zap.Error(err))
continue
}

// 6. sign covenant slash unbonding signatures
// 7. sign covenant slash unbonding signatures
slashUnbondingSigs, err := signSlashUnbondingSignatures(
btcDel,
unbondingTx,
slashUnbondingTx,
covenantPrivKey,
ce.params,
params,
&ce.config.BTCNetParams,
)
if err != nil {
Expand All @@ -233,7 +224,7 @@ func (ce *CovenantEmulator) AddCovenantSignatures(btcDels []*types.Delegation) (
metricsTimeKeeper.SetPreviousSignFinish(&finishSignTime)
timedSignDelegationLag.Observe(time.Since(startSignTime).Seconds())

// 7. collect covenant sigs
// 8. collect covenant sigs
covenantSigs = append(covenantSigs, &types.CovenantSigs{
PublicKey: ce.pk,
StakingTxHash: stakingTx.TxHash(),
Expand All @@ -243,7 +234,7 @@ func (ce *CovenantEmulator) AddCovenantSignatures(btcDels []*types.Delegation) (
})
}

// 8. submit covenant sigs
// 9. submit covenant sigs
res, err := ce.cc.SubmitCovenantSigs(covenantSigs)
if err != nil {
ce.recordMetricsFailedSignDelegations(len(covenantSigs))
Expand Down Expand Up @@ -504,12 +495,6 @@ func (ce *CovenantEmulator) covenantSigSubmissionLoop() {
for {
select {
case <-covenantSigTicker.C:
// 0. Update slashing address in case it is changed upon governance proposal
if err := ce.UpdateParams(); err != nil {
ce.logger.Debug("failed to get staking params", zap.Error(err))
continue
}

// 1. Get all pending delegations
dels, err := ce.cc.QueryPendingDelegations(limit)
if err != nil {
Expand Down Expand Up @@ -586,14 +571,14 @@ func CreateCovenantKey(keyringDir, chainID, keyName, backend, passphrase, hdPath
return krController.CreateChainKey(passphrase, hdPath)
}

func (ce *CovenantEmulator) getParamsWithRetry() (*types.StakingParams, error) {
func (ce *CovenantEmulator) getParamsByVersionWithRetry(version uint32) (*types.StakingParams, error) {
var (
params *types.StakingParams
err error
)

if err := retry.Do(func() error {
params, err = ce.cc.QueryStakingParams()
params, err = ce.cc.QueryStakingParamsByVersion(version)
if err != nil {
return err
}
Expand Down
7 changes: 3 additions & 4 deletions covenant/covenant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ func FuzzAddCovenantSig(f *testing.F) {
ce, err := covenant.NewCovenantEmulator(&covenantConfig, mockClientController, passphrase, zap.NewNop())
require.NoError(t, err)

err = ce.UpdateParams()
require.NoError(t, err)

numDels := datagen.RandomInt(r, 3) + 1
covSigsSet := make([]*types.CovenantSigs, 0, numDels)
btcDels := make([]*types.Delegation, 0, numDels)
Expand Down Expand Up @@ -83,6 +80,8 @@ func FuzzAddCovenantSig(f *testing.F) {
stakingTxBytes, err := bbntypes.SerializeBTCTx(testInfo.StakingTx)
require.NoError(t, err)
startHeight := datagen.RandomInt(r, 1000) + 100
stakingOutputIdx, err := bbntypes.GetOutputIdxInBTCTx(testInfo.StakingTx, testInfo.StakingInfo.StakingOutput)
require.NoError(t, err)
btcDel := &types.Delegation{
BtcPk: delPK,
FpBtcPks: fpPks,
Expand All @@ -91,7 +90,7 @@ func FuzzAddCovenantSig(f *testing.F) {
TotalSat: uint64(stakingValue),
UnbondingTime: uint32(unbondingTime),
StakingTxHex: hex.EncodeToString(stakingTxBytes),
StakingOutputIdx: 0,
StakingOutputIdx: stakingOutputIdx,
SlashingTxHex: testInfo.SlashingTx.ToHexStr(),
}
btcDels = append(btcDels, btcDel)
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ require (
cosmossdk.io/errors v1.0.1
cosmossdk.io/math v1.3.0
github.com/avast/retry-go/v4 v4.5.1
github.com/babylonchain/babylon v0.8.6-0.20240314161103-c2c92d903a48
github.com/babylonchain/rpc-client v0.8.0-rc.0.0.20240315010507-4e4e08fc5420
github.com/babylonchain/babylon v0.8.6-0.20240403114330-1ee4d649d955
github.com/btcsuite/btcd v0.24.0
github.com/btcsuite/btcd/btcec/v2 v2.3.2
github.com/btcsuite/btcd/btcutil v1.1.5
Expand Down Expand Up @@ -182,6 +181,7 @@ require (
github.com/prometheus/common v0.47.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/rs/cors v1.8.3 // indirect
github.com/rs/zerolog v1.32.0 // indirect
Expand Down
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX
github.com/aws/aws-sdk-go v1.44.312 h1:llrElfzeqG/YOLFFKjg1xNpZCFJ2xraIi3PqSuP+95k=
github.com/aws/aws-sdk-go v1.44.312/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/babylonchain/babylon v0.8.6-0.20240314161103-c2c92d903a48 h1:STSRSyxNmDGnGpwGrmvu0Y7MRUdWf6+jHLwRc0Y3gcY=
github.com/babylonchain/babylon v0.8.6-0.20240314161103-c2c92d903a48/go.mod h1:jR1b+5mA7BkRrXfd/PMHwk7W/RpoeQtunvjal+tKeHY=
github.com/babylonchain/rpc-client v0.8.0-rc.0.0.20240315010507-4e4e08fc5420 h1:5RMocqFkrpGtFbe1OMelSmEiikmIslbQEarTa2OoeQ4=
github.com/babylonchain/rpc-client v0.8.0-rc.0.0.20240315010507-4e4e08fc5420/go.mod h1:OqW4bUDGVuqGjZ9RQjcTOTjLaz6V50S/po0oUCbA0m8=
github.com/babylonchain/babylon v0.8.6-0.20240403114330-1ee4d649d955 h1:7XtfE9n9STrZq3j1B9qk41a+LQgSR4vwOIKd4QD2jtg=
github.com/babylonchain/babylon v0.8.6-0.20240403114330-1ee4d649d955/go.mod h1:lfeASLNJgcUsX7LEns3HRUv0k+MjzcB2q2AMasfz38M=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
Expand Down
9 changes: 5 additions & 4 deletions itest/test_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
covcc "github.com/babylonchain/covenant-emulator/clientcontroller"
covcfg "github.com/babylonchain/covenant-emulator/config"
"github.com/babylonchain/covenant-emulator/covenant"
"github.com/babylonchain/covenant-emulator/testutil"
"github.com/babylonchain/covenant-emulator/types"
)

Expand Down Expand Up @@ -115,7 +116,7 @@ func StartManager(t *testing.T) *TestManager {
func (tm *TestManager) WaitForServicesStart(t *testing.T) {
// wait for Babylon node starts
require.Eventually(t, func() bool {
params, err := tm.CovBBNClient.QueryStakingParams()
params, err := tm.CovBBNClient.QueryStakingParamsByVersion(0)
if err != nil {
return false
}
Expand Down Expand Up @@ -238,7 +239,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe
require.NoError(t, err)

unbondingTime := uint16(tm.StakingParams.MinimumUnbondingTime()) + 1
testStakingInfo := datagen.GenBTCStakingSlashingInfo(
testStakingInfo := testutil.GenBTCStakingSlashingInfo(
r,
t,
btcNetworkParams,
Expand Down Expand Up @@ -295,7 +296,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe
// delegator sig
delegatorSig, err := testStakingInfo.SlashingTx.Sign(
testStakingInfo.StakingTx,
0,
1,
slashignSpendInfo.GetPkScriptPath(),
delBtcPrivKey,
)
Expand All @@ -312,7 +313,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe
fpPks,
params.CovenantPks,
params.CovenantQuorum,
wire.NewOutPoint(&stakingTxHash, 0),
wire.NewOutPoint(&stakingTxHash, 1),
unbondingTime,
unbondingValue,
params.SlashingAddress.String(),
Expand Down
Loading

0 comments on commit ec25892

Please sign in to comment.