Skip to content

Commit

Permalink
Jury unbonding sigs submission (ethereum-optimism#91)
Browse files Browse the repository at this point in the history
* bump babylon

* Simplify jury sig submission

* Add jury submission methods
  • Loading branch information
KonradStaniec authored Sep 8, 2023
1 parent 29c6df8 commit 1b626ce
Show file tree
Hide file tree
Showing 14 changed files with 362 additions and 88 deletions.
51 changes: 47 additions & 4 deletions clientcontroller/babylon.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,32 @@ func (bc *BabylonController) SubmitJurySig(btcPubKey *types.BIP340PubKey, delPub
return res, nil
}

// SubmitJuryUnbondingSigs submits the Jury signatures via a MsgAddJuryUnbondingSigs to Babylon if the daemon runs in Jury mode
// it returns tx hash and error
func (bc *BabylonController) SubmitJuryUnbondingSigs(
btcPubKey *types.BIP340PubKey,
delPubKey *types.BIP340PubKey,
stakingTxHash string,
unbondingSig *types.BIP340Signature,
slashUnbondingSig *types.BIP340Signature,
) (*provider.RelayerTxResponse, error) {
msg := &btcstakingtypes.MsgAddJuryUnbondingSigs{
Signer: bc.MustGetTxSigner(),
ValPk: btcPubKey,
DelPk: delPubKey,
StakingTxHash: stakingTxHash,
UnbondingTxSig: unbondingSig,
SlashingUnbondingTxSig: slashUnbondingSig,
}

res, err := bc.reliablySendMsg(msg)
if err != nil {
return nil, err
}

return res, nil
}

// SubmitFinalitySig submits the finality signature via a MsgAddVote to Babylon
func (bc *BabylonController) SubmitFinalitySig(btcPubKey *types.BIP340PubKey, blockHeight uint64, blockHash []byte, sig *types.SchnorrEOTSSig) (*provider.RelayerTxResponse, error) {
msg := &finalitytypes.MsgAddFinalitySig{
Expand Down Expand Up @@ -477,8 +503,6 @@ func (bc *BabylonController) QueryHeightWithLastPubRand(btcPubKey *types.BIP340P
// QueryPendingBTCDelegations queries BTC delegations that need a Jury sig
// it is only used when the program is running in Jury mode
func (bc *BabylonController) QueryPendingBTCDelegations() ([]*btcstakingtypes.BTCDelegation, error) {
var delegations []*btcstakingtypes.BTCDelegation

ctx, cancel := getContextWithCancel(bc.timeout)
defer cancel()

Expand All @@ -492,9 +516,28 @@ func (bc *BabylonController) QueryPendingBTCDelegations() ([]*btcstakingtypes.BT
if err != nil {
return nil, fmt.Errorf("failed to query BTC delegations: %v", err)
}
delegations = append(delegations, res.BtcDelegations...)

return delegations, nil
return res.BtcDelegations, nil
}

// QueryUnbondindBTCDelegations queries BTC delegations that need a Jury sig for unbodning
// it is only used when the program is running in Jury mode
func (bc *BabylonController) QueryUnbondindBTCDelegations() ([]*btcstakingtypes.BTCDelegation, error) {
ctx, cancel := getContextWithCancel(bc.timeout)
defer cancel()

clientCtx := sdkclient.Context{Client: bc.provider.RPCClient}

queryClient := btcstakingtypes.NewQueryClient(clientCtx)

// query all the unsigned delegations
queryRequest := &btcstakingtypes.QueryUnbondingBTCDelegationsRequest{}
res, err := queryClient.UnbondingBTCDelegations(ctx, queryRequest)
if err != nil {
return nil, fmt.Errorf("failed to query BTC delegations: %v", err)
}

return res.BtcDelegations, nil
}

// QueryValidators queries BTC validators
Expand Down
16 changes: 16 additions & 0 deletions clientcontroller/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ type ClientController interface {
// SubmitJurySig submits the Jury signature via a MsgAddJurySig to Babylon if the daemon runs in Jury mode
// it returns tx hash and error
SubmitJurySig(btcPubKey *types.BIP340PubKey, delPubKey *types.BIP340PubKey, stakingTxHash string, sig *types.BIP340Signature) (*provider.RelayerTxResponse, error)

// SubmitJuryUnbondingSigs submits the Jury signatures via a MsgAddJuryUnbondingSigs to Babylon if the daemon runs in Jury mode
// it returns tx hash and error
SubmitJuryUnbondingSigs(
btcPubKey *types.BIP340PubKey,
delPubKey *types.BIP340PubKey,
stakingTxHash string,
unbondingSig *types.BIP340Signature,
slashUnbondingSig *types.BIP340Signature,
) (*provider.RelayerTxResponse, error)

// SubmitFinalitySig submits the finality signature via a MsgAddVote to Babylon
SubmitFinalitySig(btcPubKey *types.BIP340PubKey, blockHeight uint64, blockHash []byte, sig *types.SchnorrEOTSSig) (*provider.RelayerTxResponse, error)

Expand All @@ -71,6 +82,11 @@ type ClientController interface {
// QueryPendingBTCDelegations queries BTC delegations that need a Jury signature
// it is only used when the program is running in Jury mode
QueryPendingBTCDelegations() ([]*btcstakingtypes.BTCDelegation, error)

// QueryUnbondindBTCDelegations queries BTC delegations that need a Jury sig for unbodning
// it is only used when the program is running in Jury mode
QueryUnbondindBTCDelegations() ([]*btcstakingtypes.BTCDelegation, error)

// QueryValidatorVotingPower queries the voting power of the validator at a given height
QueryValidatorVotingPower(btcPubKey *types.BIP340PubKey, blockHeight uint64) (uint64, error)
// QueryLatestFinalisedBlocks returns the latest `count` finalised blocks
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/btcsuite/btcd v0.23.5-0.20230228185050-38331963bddd
github.com/btcsuite/btcd/btcec/v2 v2.3.2
github.com/btcsuite/btcd/btcutil v1.1.3
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2
github.com/cometbft/cometbft v0.37.2
github.com/cosmos/cosmos-sdk v0.47.3
github.com/cosmos/go-bip39 v1.0.0
Expand All @@ -25,6 +26,7 @@ require (
go.etcd.io/bbolt v1.3.7
go.uber.org/zap v1.24.0
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
golang.org/x/sync v0.1.0
google.golang.org/grpc v1.56.1
google.golang.org/protobuf v1.31.0
)
Expand Down Expand Up @@ -57,7 +59,6 @@ require (
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect
github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d // indirect
github.com/btcsuite/btcd/btcutil/psbt v1.1.8 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect
github.com/btcsuite/btcwallet v0.16.10-0.20230621165747-9c21f464ce13 // indirect
github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2 // indirect
Expand Down Expand Up @@ -268,7 +269,6 @@ require (
golang.org/x/mod v0.8.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/oauth2 v0.8.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/term v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
Expand Down Expand Up @@ -303,7 +303,7 @@ require (
)

replace (
github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20230906061737-c23587edbcab
github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20230907054038-66908792bb08
github.com/cosmos/ibc-go/v7 => github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX
github.com/aws/aws-sdk-go v1.44.203 h1:pcsP805b9acL3wUqa4JR2vg1k2wnItkDYNvfmcy6F+U=
github.com/aws/aws-sdk-go v1.44.203/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-private v0.0.0-20230906061737-c23587edbcab h1:fuZej701RUESFOrHCUmeugPFvZ/F52vJJQQG1T6NVxo=
github.com/babylonchain/babylon-private v0.0.0-20230906061737-c23587edbcab/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako=
github.com/babylonchain/babylon-private v0.0.0-20230907054038-66908792bb08 h1:MgtzQhnyMQhBBvNd21teyOSo12+rJofGDI0c09iFPhA=
github.com/babylonchain/babylon-private v0.0.0-20230907054038-66908792bb08/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako=
github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61 h1:0NPV8yfawKAYrw96b2ZR70QHIAwB1QcKWyf2BWcRvmU=
github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61/go.mod h1:OOcjKIRku/j1Xs1RgKK0yvKRrJ5iFuZYMetR1n3yMlc=
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
Expand Down
80 changes: 80 additions & 0 deletions itest/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,3 +452,83 @@ func TestValidatorUnbondingSigSubmission(t *testing.T) {
return true
}, 1*time.Minute, eventuallyPollTime)
}

func TestJuryUnbondingSigSubmission(t *testing.T) {
tm := StartManagerWithValidator(t, 1, true)
defer tm.Stop(t)
app := tm.Va
valIns := app.ListValidatorInstances()[0]

// send BTC delegation and make sure it's deep enough in btclightclient module
delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount)

var (
dels []*btcstakingtypes.BTCDelegation
err error
)
require.Eventually(t, func() bool {
dels, err = tm.BabylonClient.QueryPendingBTCDelegations()
if err != nil {
return false
}
return len(dels) == 1
}, eventuallyWaitTimeOut, eventuallyPollTime)
require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey))

currentBtcTip, err := tm.BabylonClient.QueryBtcLightClientTip()
require.NoError(t, err)
params, err := tm.BabylonClient.GetStakingParams()
require.NoError(t, err)
require.Eventually(t, func() bool {
dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valIns.GetBtcPkBIP340(), 1000)
if err != nil {
return false
}
status := dels[0].GetStatus(currentBtcTip.Height, params.FinalizationTimeoutBlocks)
return len(dels) == 1 && status == btcstakingtypes.BTCDelegationStatus_ACTIVE
}, eventuallyWaitTimeOut, eventuallyPollTime)
require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey))

tm.InsertBTCUnbonding(t, delData.StakingTx, delData.DelegatorPrivKey, valIns.MustGetBtcPk())

require.Eventually(t, func() bool {
dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valIns.GetBtcPkBIP340(), 1000)
if err != nil {
return false
}
return len(dels) == 1 && dels[0].BtcUndelegation != nil
}, eventuallyWaitTimeOut, eventuallyPollTime)

dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valIns.GetBtcPkBIP340(), 1000)
require.NoError(t, err)
delegationWithUndelegation := dels[0]

validatorPrivKey, err := valIns.BtcPrivKey()
require.NoError(t, err)

tm.AddValidatorUnbondingSignature(
t,
delegationWithUndelegation,
validatorPrivKey,
)

// after providing validator unbodning signature, we should wait for jury to provide both valid signatures
require.Eventually(t, func() bool {
dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valIns.GetBtcPkBIP340(), 1000)
if err != nil {
return false
}

if len(dels) != 1 {
return false
}

del := dels[0]

if del.BtcUndelegation == nil {
return false
}

return del.BtcUndelegation.HasJurySigs()
}, 1*time.Minute, eventuallyPollTime)
}
32 changes: 32 additions & 0 deletions itest/test_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,37 @@ func (tm *TestManager) AddJurySignature(t *testing.T, btcDel *bstypes.BTCDelegat
return res
}

// delegation must containt undelgation object
func (tm *TestManager) AddValidatorUnbondingSignature(
t *testing.T,
btcDel *bstypes.BTCDelegation,
validatorSk *btcec.PrivateKey,
) {
stakingTx := btcDel.StakingTx
stakingMsgTx, err := stakingTx.ToMsgTx()
require.NoError(t, err)

unbondingTx := btcDel.BtcUndelegation.UnbondingTx

valSig, err := unbondingTx.Sign(
stakingMsgTx,
stakingTx.Script,
validatorSk,
btcNetworkParams,
)
require.NoError(t, err)

stakingTxHash := stakingMsgTx.TxHash().String()

_, err = tm.BabylonClient.SubmitValidatorUnbondingSig(
btcDel.ValBtcPk,
btcDel.BtcPk,
stakingTxHash,
valSig,
)
require.NoError(t, err)
}

func (tm *TestManager) GetJuryPrivKey(t *testing.T) *btcec.PrivateKey {
kr := tm.Va.GetKeyring()
juryKeyName := tm.BabylonHandler.GetJuryKeyName()
Expand Down Expand Up @@ -320,6 +351,7 @@ func defaultValidatorConfig(keyringDir, testDir string, isJury bool) *valcfg.Con
cfg.BabylonConfig.GasAdjustment = 5
cfg.DatabaseConfig.Path = filepath.Join(testDir, "db")
cfg.JuryMode = isJury
cfg.JuryModeConfig.QueryInterval = 7 * time.Second
cfg.UnbondingSigSubmissionInterval = 3 * time.Second

return &cfg
Expand Down
Loading

0 comments on commit 1b626ce

Please sign in to comment.