Skip to content

Commit

Permalink
Encapsulate signing into separate function (#187)
Browse files Browse the repository at this point in the history
  • Loading branch information
KonradStaniec authored Jul 25, 2024
1 parent 130fd68 commit 6ba8d4f
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 111 deletions.
4 changes: 2 additions & 2 deletions itest/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ func StartManager(
err = walletClient.UnlockWallet(20)
require.NoError(t, err)

walletPrivKey, err := walletClient.DumpPrivateKey(minerAddressDecoded)
walletPrivKey, err := c.DumpPrivKey(minerAddressDecoded)
require.NoError(t, err)

interceptor, err := signal.Intercept()
Expand Down Expand Up @@ -334,7 +334,7 @@ func StartManager(
Db: dbbackend,
Sa: stakerApp,
BabylonClient: bl,
WalletPrivKey: walletPrivKey,
WalletPrivKey: walletPrivKey.PrivKey,
MinerAddr: minerAddressDecoded,
serverStopper: &interceptor,
wg: &wg,
Expand Down
49 changes: 42 additions & 7 deletions staker/babylontypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ func (app *StakerApp) buildOwnedDelegation(

slashingFee := app.getSlashingFee(externalData.babylonParams.MinSlashingTxFeeSat)

slashingTx, slashingTxSig, err := buildSlashingTxAndSig(slashingFee, externalData, storedTx, app.network)
stakingSlashingTx, stakingSlashingSpendInfo, err := slashingTxForStakingTx(
slashingFee,
externalData,
storedTx,
app.network,
)
if err != nil {
// This is truly unexpected, most probably programming error we have
// valid and btc confirmed staking transacion, but for some reason we cannot
Expand All @@ -55,9 +60,9 @@ func (app *StakerApp) buildOwnedDelegation(
// in case of estimation failure (25 sat/byte)
unbondingTxFeeRatePerKb := btcutil.Amount(app.feeEstimator.EstimateFeePerKb())

undelegationData, err := createUndelegationData(
undelegationDesc, err := createUndelegationData(
storedTx,
externalData.stakerPrivKey,
externalData.stakerPublicKey,
externalData.babylonParams.CovenantPks,
externalData.babylonParams.CovenantQuruomThreshold,
externalData.babylonParams.SlashingAddress,
Expand All @@ -74,16 +79,46 @@ func (app *StakerApp) buildOwnedDelegation(
return nil, fmt.Errorf("error creating undelegation data: %w", err)
}

stakingSlashingSig, err := app.signTaprootScriptSpendUsingWallet(
stakingSlashingTx,
storedTx.StakingTx.TxOut[storedTx.StakingOutputIndex],
stakerAddress,
&stakingSlashingSpendInfo.RevealedLeaf,
&stakingSlashingSpendInfo.ControlBlock,
)

if err != nil {
return nil, fmt.Errorf("error signing slashing transaction for staking transaction: %w", err)
}

unbondingSlashingSig, err := app.signTaprootScriptSpendUsingWallet(
undelegationDesc.SlashUnbondingTransaction,
undelegationDesc.UnbondingTransaction.TxOut[0],
stakerAddress,
&undelegationDesc.SlashUnbondingTransactionSpendInfo.RevealedLeaf,
&undelegationDesc.SlashUnbondingTransactionSpendInfo.ControlBlock,
)

if err != nil {
return nil, fmt.Errorf("error signing slashing transaction for unbonding transaction: %w", err)
}

dg := createDelegationData(
externalData.stakerPrivKey.PubKey(),
externalData.stakerPublicKey,
req.inclusionBlock,
req.txIndex,
storedTx,
slashingTx,
slashingTxSig,
stakingSlashingTx,
stakingSlashingSig,
externalData.babylonStakerAddr,
stakingTxInclusionProof,
undelegationData,
&cl.UndelegationData{
UnbondingTransaction: undelegationDesc.UnbondingTransaction,
UnbondingTxValue: undelegationDesc.UnbondingTxValue,
UnbondingTxUnbondingTime: undelegationDesc.UnbondingTxUnbondingTime,
SlashUnbondingTransaction: undelegationDesc.SlashUnbondingTransaction,
SlashUnbondingTransactionSig: unbondingSlashingSig,
},
)

return dg, nil
Expand Down
106 changes: 77 additions & 29 deletions staker/stakerapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ import (
)

type externalDelegationData struct {
// stakerPrivKey needs to be retrieved from btc wallet
stakerPrivKey *btcec.PrivateKey
// babylonStakerAddr the bech32 bbn address to receive staking rewards.
babylonStakerAddr sdk.AccAddress
// stakerPublicKey the public key of the staker.
stakerPublicKey *btcec.PublicKey
// params retrieved from babylon
babylonParams *cl.StakingParams
}
Expand Down Expand Up @@ -768,36 +768,21 @@ func (app *StakerApp) mustBuildInclusionProof(req *sendDelegationRequest) []byte
return proof
}

func (app *StakerApp) stakerPrivateKey(stakerAddress btcutil.Address) (*btcec.PrivateKey, error) {
err := app.wc.UnlockWallet(defaultWalletUnlockTimeout)

if err != nil {
return nil, err
}

privkey, err := app.wc.DumpPrivateKey(stakerAddress)

if err != nil {
return nil, err
}

return privkey, nil
}

func (app *StakerApp) retrieveExternalDelegationData(stakerAddress btcutil.Address) (*externalDelegationData, error) {
params, err := app.babylonClient.Params()
if err != nil {
return nil, err
}

stakerPrivKey, err := app.stakerPrivateKey(stakerAddress)
stakerPublicKey, err := app.wc.AddressPublicKey(stakerAddress)

if err != nil {
return nil, err
}

return &externalDelegationData{
stakerPrivKey: stakerPrivKey,
babylonStakerAddr: app.babylonClient.GetKeyAddress(),
stakerPublicKey: stakerPublicKey,
babylonParams: params,
}, nil
}
Expand All @@ -808,7 +793,8 @@ func (app *StakerApp) sendUnbondingTxToBtcWithWitness(
storedTx *stakerdb.StoredTransaction,
unbondingData *stakerdb.UnbondingStoreData,
) error {
privkey, err := app.stakerPrivateKey(stakerAddress)

stakerPubKey, err := app.wc.AddressPublicKey(stakerAddress)

if err != nil {
app.logger.WithFields(logrus.Fields{
Expand All @@ -825,8 +811,8 @@ func (app *StakerApp) sendUnbondingTxToBtcWithWitness(
return err
}

witness, err := createWitnessToSendUnbondingTx(
privkey,
unbondingSpendInfo, err := buildUnbondingSpendInfo(
stakerPubKey,
storedTx,
unbondingData,
params,
Expand All @@ -838,7 +824,37 @@ func (app *StakerApp) sendUnbondingTxToBtcWithWitness(
app.logger.WithFields(logrus.Fields{
"stakingTxHash": stakingTxHash,
"err": err,
}).Fatalf("Failed to create witness to send unbonding tx to btc")
}).Fatalf("failed to create necessary spend info to send unbonding tx")
}

stakerUnbondingSig, err := app.signTaprootScriptSpendUsingWallet(
unbondingData.UnbondingTx,
storedTx.StakingTx.TxOut[storedTx.StakingOutputIndex],
stakerAddress,
&unbondingSpendInfo.RevealedLeaf,
&unbondingSpendInfo.ControlBlock,
)

if err != nil {
return fmt.Errorf("failed to send unbondingtx. wallet signing error: %w", err)
}

covenantSigantures := createWitnessSignaturesForPubKeys(
params.CovenantPks,
unbondingData.CovenantSignatures,
)

witness, err := unbondingSpendInfo.CreateUnbondingPathWitness(
covenantSigantures,
stakerUnbondingSig,
)

if err != nil {
// we panic here, as our data should be correct at this point
app.logger.WithFields(logrus.Fields{
"stakingTxHash": stakingTxHash,
"err": err,
}).Fatalf("failed to build witness from correct data")
}

unbondingTx := unbondingData.UnbondingTx
Expand Down Expand Up @@ -1590,6 +1606,37 @@ func (app *StakerApp) waitForSpendConfirmation(stakingTxHash chainhash.Hash, ev
}
}

func (app *StakerApp) signTaprootScriptSpendUsingWallet(
txToSign *wire.MsgTx,
fundingOutput *wire.TxOut,
signerAddress btcutil.Address,
leaf *txscript.TapLeaf,
controlBlock *txscript.ControlBlock,
) (*schnorr.Signature, error) {

if err := app.wc.UnlockWallet(defaultWalletUnlockTimeout); err != nil {
return nil, fmt.Errorf("failed to unlock wallet before signing: %w", err)
}

req := &walletcontroller.TaprootSigningRequest{
FundingOutput: fundingOutput,
TxToSign: txToSign,
SignerAddress: signerAddress,
SpendDescription: &walletcontroller.SpendPathDescription{
ScriptLeaf: leaf,
ControlBlock: controlBlock,
},
}

resp, err := app.wc.SignOneInputTaprootSpendingTransaction(req)

if err != nil {
return nil, err
}

return resp.Signature, nil
}

// SpendStake spends stake identified by stakingTxHash. Stake can be currently locked in
// two types of outputs:
// 1. Staking output - this is output which is created by staking transaction
Expand Down Expand Up @@ -1643,7 +1690,7 @@ func (app *StakerApp) SpendStake(stakingTxHash *chainhash.Hash) (*chainhash.Hash
return nil, nil, fmt.Errorf("cannot spend staking output. Error getting params: %w", err)
}

privKey, err := app.stakerPrivateKey(destAddress)
pubKey, err := app.wc.AddressPublicKey(destAddress)

if err != nil {
return nil, nil, fmt.Errorf("cannot spend staking output. Error getting private key: %w", err)
Expand All @@ -1652,7 +1699,7 @@ func (app *StakerApp) SpendStake(stakingTxHash *chainhash.Hash) (*chainhash.Hash
currentFeeRate := app.feeEstimator.EstimateFeePerKb()

spendStakeTxInfo, err := createSpendStakeTxFromStoredTx(
privKey.PubKey(),
pubKey,
params.CovenantPks,
params.CovenantQuruomThreshold,
tx,
Expand All @@ -1665,11 +1712,12 @@ func (app *StakerApp) SpendStake(stakingTxHash *chainhash.Hash) (*chainhash.Hash
return nil, nil, err
}

stakerSig, err := staking.SignTxWithOneScriptSpendInputFromTapLeaf(
stakerSig, err := app.signTaprootScriptSpendUsingWallet(
spendStakeTxInfo.spendStakeTx,
spendStakeTxInfo.fundingOutput,
privKey,
spendStakeTxInfo.fundingOutputSpendInfo.RevealedLeaf,
destAddress,
&spendStakeTxInfo.fundingOutputSpendInfo.RevealedLeaf,
&spendStakeTxInfo.fundingOutputSpendInfo.ControlBlock,
)

if err != nil {
Expand Down
Loading

0 comments on commit 6ba8d4f

Please sign in to comment.