Skip to content

Commit

Permalink
chore: Bump babylon and fix pre-approval (#23)
Browse files Browse the repository at this point in the history
* bump babylon and fix pre-approval

* fix pre-approval

* update changelog

* bump babylon
  • Loading branch information
gitferry authored Oct 16, 2024
1 parent e23e7d1 commit 407a9d1
Show file tree
Hide file tree
Showing 12 changed files with 95 additions and 38 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)

## Unreleased

## v0.5.0

### Bug fixes

* [#23](https://github.com/babylonlabs-io/covenant-emulator/pull/23) Fix pre-approval flow

### Improvements

* [#20](https://github.com/babylonlabs-io/covenant-emulator/pull/20) Add signing behind
Expand Down
13 changes: 12 additions & 1 deletion clientcontroller/babylon.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ func (bc *BabylonController) QueryActiveDelegations(limit uint64) ([]*types.Dele
return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_ACTIVE, limit)
}

func (bc *BabylonController) QueryVerifiedDelegations(limit uint64) ([]*types.Delegation, error) {
return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_VERIFIED, limit)
}

// queryDelegationsWithStatus queries BTC delegations that need a Covenant signature
// with the given status (either pending or unbonding)
// it is only used when the program is running in Covenant mode
Expand Down Expand Up @@ -273,6 +277,7 @@ func DelegationRespToDelegation(del *btcstakingtypes.BTCDelegationResponse) (*ty
BtcPk: del.BtcPk.MustToBTCPK(),
FpBtcPks: fpBtcPks,
TotalSat: btcutil.Amount(del.TotalSat),
StakingTime: del.StakingTime,
StartHeight: del.StartHeight,
EndHeight: del.EndHeight,
StakingTxHex: del.StakingTxHex,
Expand Down Expand Up @@ -351,12 +356,18 @@ func (bc *BabylonController) CreateBTCDelegation(
unbondingValue int64,
unbondingSlashingTx *btcstakingtypes.BTCSlashingTx,
delUnbondingSlashingSig *bbntypes.BIP340Signature,
isPreApproval bool,
) (*types.TxResponse, error) {
fpBtcPks := make([]bbntypes.BIP340PubKey, 0, len(fpPks))
for _, v := range fpPks {
fpBtcPks = append(fpBtcPks, *bbntypes.NewBIP340PubKeyFromBTCPK(v))
}

var inclusionProof *btcstakingtypes.InclusionProof
if !isPreApproval {
inclusionProof = btcstakingtypes.NewInclusionProof(stakingTxInfo.Key, stakingTxInfo.Proof)
}

msg := &btcstakingtypes.MsgCreateBTCDelegation{
StakerAddr: bc.mustGetTxSigner(),
Pop: pop,
Expand All @@ -365,7 +376,7 @@ func (bc *BabylonController) CreateBTCDelegation(
StakingTime: stakingTime,
StakingValue: stakingValue,
StakingTx: stakingTxInfo.Transaction,
StakingTxInclusionProof: btcstakingtypes.NewInclusionProof(stakingTxInfo.Key, stakingTxInfo.Proof),
StakingTxInclusionProof: inclusionProof,
SlashingTx: slashingTx,
DelegatorSlashingSig: delSlashingSig,
UnbondingTx: unbondingTx,
Expand Down
8 changes: 4 additions & 4 deletions covenant/covenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ func (ce *CovenantEmulator) AddCovenantSignatures(btcDels []*types.Delegation) (
// - CheckpointFinalizationTimeout
unbondingTime := btcDel.UnbondingTime
minUnbondingTime := params.MinimumUnbondingTime()
if uint64(unbondingTime) <= minUnbondingTime {
if uint32(unbondingTime) <= minUnbondingTime {
ce.logger.Error("invalid unbonding time",
zap.Uint64("min_unbonding_time", minUnbondingTime),
zap.Uint32("min_unbonding_time", minUnbondingTime),
zap.Uint16("got_unbonding_time", unbondingTime),
)
continue
Expand Down Expand Up @@ -374,7 +374,7 @@ func decodeDelegationTransactions(del *types.Delegation, params *types.StakingPa
}

// 2. verify the transactions
if err := btcstaking.CheckTransactions(
if err := btcstaking.CheckSlashingTxMatchFundingTx(
slashingMsgTx,
stakingMsgTx,
del.StakingOutputIdx,
Expand Down Expand Up @@ -404,7 +404,7 @@ func decodeUndelegationTransactions(del *types.Delegation, params *types.Staking
}

// 2. verify transactions
if err := btcstaking.CheckTransactions(
if err := btcstaking.CheckSlashingTxMatchFundingTx(
unbondingSlashingMsgTx,
unbondingMsgTx,
0,
Expand Down
9 changes: 5 additions & 4 deletions covenant/covenant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func FuzzAddCovenantSig(f *testing.F) {
// generate BTC delegation
delSK, delPK, err := datagen.GenRandomBTCKeyPair(r)
require.NoError(t, err)
stakingTimeBlocks := uint16(testutil.RandRange(r, int(params.MinStakingTime), int(params.MaxStakingTime)))
stakingTimeBlocks := uint32(testutil.RandRange(r, int(params.MinStakingTime), int(params.MaxStakingTime)))
stakingValue := int64(testutil.RandRange(r, int(params.MinStakingValue), int(params.MaxStakingValue)))
unbondingTime := uint16(params.MinimumUnbondingTime()) + 1
fpNum := datagen.RandomInt(r, 5) + 1
Expand All @@ -80,22 +80,23 @@ func FuzzAddCovenantSig(f *testing.F) {
fpPks,
params.CovenantPks,
params.CovenantQuorum,
stakingTimeBlocks,
uint16(stakingTimeBlocks),
stakingValue,
params.SlashingPkScript,
params.SlashingRate,
unbondingTime,
)
stakingTxBytes, err := bbntypes.SerializeBTCTx(testInfo.StakingTx)
require.NoError(t, err)
startHeight := datagen.RandomInt(r, 1000) + 100
startHeight := uint32(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,
StakingTime: stakingTimeBlocks,
StartHeight: startHeight, // not relevant here
EndHeight: startHeight + uint64(stakingTimeBlocks),
EndHeight: startHeight + stakingTimeBlocks,
TotalSat: btcutil.Amount(stakingValue),
UnbondingTime: unbondingTime,
StakingTxHex: hex.EncodeToString(stakingTxBytes),
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ require (
cosmossdk.io/errors v1.0.1
cosmossdk.io/math v1.3.0
github.com/avast/retry-go/v4 v4.5.1
github.com/babylonlabs-io/babylon v0.12.0
github.com/babylonlabs-io/babylon v0.13.0
github.com/btcsuite/btcd v0.24.2
github.com/btcsuite/btcd/btcec/v2 v2.3.2
github.com/btcsuite/btcd/btcutil v1.1.5
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0
github.com/cosmos/cosmos-sdk v0.50.6
github.com/cosmos/go-bip39 v1.0.0
github.com/cosmos/relayer/v2 v2.5.2
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0
github.com/golang/mock v1.6.0
github.com/jessevdk/go-flags v1.5.0
github.com/jsternberg/zap-logfmt v1.3.0
Expand Down Expand Up @@ -91,7 +92,6 @@ require (
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +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/babylonlabs-io/babylon v0.12.0 h1:s2OTcxpk0RzrkVBnVTfnPdJVYDSqnm/33YKPQqEzNCE=
github.com/babylonlabs-io/babylon v0.12.0/go.mod h1:ZOrTde9vs2xoqGTFw4xhupu2CMulnpywiuk0eh4kPOw=
github.com/babylonlabs-io/babylon v0.13.0 h1:h7cazmFmItePvZHEbLhDbsq2l7xN4e2AjDHRM7zDLkg=
github.com/babylonlabs-io/babylon v0.13.0/go.mod h1:cxRwVqVLoJ39FpyovTEHJLu1lwwrM1tE8davu7nRHwY=
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
22 changes: 16 additions & 6 deletions itest/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,37 @@ package e2etest

import (
"testing"
"time"
)

var (
stakingTime = uint16(100)
stakingAmount = int64(20000)
)

// TestCovenantEmulatorLifeCycle tests the whole life cycle of a finality-provider
// creation -> registration -> randomness commitment ->
// activation with BTC delegation and Covenant sig ->
// vote submission -> block finalization
// TestCovenantEmulatorLifeCycle tests the whole life cycle of a covenant emulator
// in two flows depending on whether the delegation is following pre-approval flow
func TestCovenantEmulatorLifeCycle(t *testing.T) {
tm, btcPks := StartManagerWithFinalityProvider(t, 1)
defer tm.Stop(t)

// send a BTC delegation
_ = tm.InsertBTCDelegation(t, btcPks, stakingTime, stakingAmount)
// send a BTC delegation that is not following pre-approval flow
_ = tm.InsertBTCDelegation(t, btcPks, stakingTime, stakingAmount, false)

// check the BTC delegation is pending
_ = tm.WaitForNPendingDels(t, 1)

// check the BTC delegation is active
_ = tm.WaitForNActiveDels(t, 1)

// send a BTC delegation that is following pre-approval flow
_ = tm.InsertBTCDelegation(t, btcPks, stakingTime, stakingAmount, true)

// check the BTC delegation is pending
_ = tm.WaitForNPendingDels(t, 1)

time.Sleep(10 * time.Second)

// check the BTC delegation is verified
_ = tm.WaitForNVerifiedDels(t, 1)
}
36 changes: 32 additions & 4 deletions itest/test_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,34 @@ func (tm *TestManager) WaitForNActiveDels(t *testing.T, n int) []*types.Delegati
return dels
}

func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKey, stakingTime uint16, stakingAmount int64) *TestDelegationData {
func (tm *TestManager) WaitForNVerifiedDels(t *testing.T, n int) []*types.Delegation {
var (
dels []*types.Delegation
err error
)
require.Eventually(t, func() bool {
dels, err = tm.CovBBNClient.QueryVerifiedDelegations(
tm.CovenanConfig.DelegationLimit,
)
if err != nil {
return false
}
return len(dels) == n
}, eventuallyWaitTimeOut, eventuallyPollTime)

t.Logf("delegations are verified")

return dels
}

// InsertBTCDelegation inserts a BTC delegation to Babylon
// isPreApproval indicates whether the delegation follows
// pre-approval flow, if so, the inclusion proof is nil
func (tm *TestManager) InsertBTCDelegation(
t *testing.T,
fpPks []*btcec.PublicKey, stakingTime uint16, stakingAmount int64,
isPreApproval bool,
) *TestDelegationData {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
params := tm.StakingParams

Expand Down Expand Up @@ -284,14 +311,14 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe
require.NoError(t, err)
txInfo := btcctypes.NewTransactionInfo(&btcctypes.TransactionKey{Index: 1, Hash: btcHeader.Hash()}, serializedStakingTx, blockWithStakingTx.SpvProof.MerkleNodes)

slashignSpendInfo, err := testStakingInfo.StakingInfo.SlashingPathSpendInfo()
slashingSpendInfo, err := testStakingInfo.StakingInfo.SlashingPathSpendInfo()
require.NoError(t, err)

// delegator sig
delegatorSig, err := testStakingInfo.SlashingTx.Sign(
testStakingInfo.StakingTx,
1,
slashignSpendInfo.GetPkScriptPath(),
slashingSpendInfo.GetPkScriptPath(),
delBtcPrivKey,
)
require.NoError(t, err)
Expand Down Expand Up @@ -345,7 +372,8 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe
uint32(unbondingTime),
unbondingValue,
testUnbondingInfo.SlashingTx,
unbondingSig)
unbondingSig,
isPreApproval)
require.NoError(t, err)

t.Log("successfully submitted a BTC delegation")
Expand Down
2 changes: 1 addition & 1 deletion tools/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.21

toolchain go1.21.4

require github.com/babylonlabs-io/babylon v0.12.0
require github.com/babylonlabs-io/babylon v0.13.0

require (
cloud.google.com/go v0.112.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions tools/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,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/babylonlabs-io/babylon v0.12.0 h1:s2OTcxpk0RzrkVBnVTfnPdJVYDSqnm/33YKPQqEzNCE=
github.com/babylonlabs-io/babylon v0.12.0/go.mod h1:ZOrTde9vs2xoqGTFw4xhupu2CMulnpywiuk0eh4kPOw=
github.com/babylonlabs-io/babylon v0.13.0 h1:h7cazmFmItePvZHEbLhDbsq2l7xN4e2AjDHRM7zDLkg=
github.com/babylonlabs-io/babylon v0.13.0/go.mod h1:cxRwVqVLoJ39FpyovTEHJLu1lwwrM1tE8davu7nRHwY=
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
15 changes: 8 additions & 7 deletions types/delegation.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package types

import (
"github.com/btcsuite/btcd/btcutil"
"math"

"github.com/btcsuite/btcd/btcutil"

bbn "github.com/babylonlabs-io/babylon/types"

"github.com/btcsuite/btcd/btcec/v2"
Expand All @@ -16,12 +17,14 @@ type Delegation struct {
// The Bitcoin secp256k1 PKs of the finality providers that
// this BTC delegation delegates to
FpBtcPks []*btcec.PublicKey
// The number of blocks for which the delegation is locked on BTC chain
StakingTime uint32
// The start BTC height of the BTC delegation
// it is the start BTC height of the timelock
StartHeight uint64
StartHeight uint32
// The end height of the BTC delegation
// it is the end BTC height of the timelock - w
EndHeight uint64
EndHeight uint32
// The total amount of BTC stakes in this delegation
// quantified in satoshi
TotalSat btcutil.Amount
Expand Down Expand Up @@ -52,14 +55,12 @@ func (d *Delegation) HasCovenantQuorum(quorum uint32) bool {
}

func (d *Delegation) GetStakingTime() uint16 {
diff := d.EndHeight - d.StartHeight

if diff > math.MaxUint16 {
if d.StakingTime > math.MaxUint16 {
// In a valid delegation, EndHeight is always greater than StartHeight and it is always uint16 value
panic("invalid delegation in database")
}

return uint16(diff)
return uint16(d.StakingTime)
}

// Undelegation signalizes that the delegation is being undelegated
Expand Down
10 changes: 5 additions & 5 deletions types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (

type StakingParams struct {
// K-deep
ComfirmationTimeBlocks uint64
ComfirmationTimeBlocks uint32
// W-deep
FinalizationTimeoutBlocks uint64
FinalizationTimeoutBlocks uint32

// Minimum amount of tx fee (quantified in Satoshi) needed for the pre-signed slashing tx
MinSlashingTxFeeSat btcutil.Amount
Expand Down Expand Up @@ -52,9 +52,9 @@ type StakingParams struct {
// MinimumUnbondingTime returns the minimum unbonding time. It is the bigger value from:
// - MinUnbondingTime
// - CheckpointFinalizationTimeout
func (p *StakingParams) MinimumUnbondingTime() uint64 {
return sdkmath.Max[uint64](
uint64(p.MinUnbondingTime),
func (p *StakingParams) MinimumUnbondingTime() uint32 {
return sdkmath.Max[uint32](
p.MinUnbondingTime,
p.FinalizationTimeoutBlocks,
)
}

0 comments on commit 407a9d1

Please sign in to comment.