From 829601a9dea0b2667459342c9319d6d7f91d7e79 Mon Sep 17 00:00:00 2001 From: KonradStaniec Date: Mon, 2 Dec 2024 12:58:55 +0100 Subject: [PATCH] Enforce that unbonding tx always has version 2 (#311) - Enforces that unbonding tx always have version `2` --- CHANGELOG.md | 7 +++++++ btcstaking/staking.go | 12 ++++++++---- btcstaking/staking_test.go | 40 +++++++++++++++++++++++++++++++++++++- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e17af0041..0bfc88172 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## Unreleased +### Improvements + +- [#305](https://github.com/babylonlabs-io/babylon/pull/305) chore: add more error logs to `VerifyInclusionProofAndGetHeight` +- [#304](https://github.com/babylonlabs-io/babylon/pull/304) Add highest voted height to finality provider +- [#311](https://github.com/babylonlabs-io/babylon/pull/311) Enforce version 2 +for unbonding transactions + ## v0.17.1 ### Bug fixes diff --git a/btcstaking/staking.go b/btcstaking/staking.go index 8a04f7342..2a1a5d7b6 100644 --- a/btcstaking/staking.go +++ b/btcstaking/staking.go @@ -229,14 +229,14 @@ func IsSimpleTransfer(tx *wire.MsgTx) error { // - the transaction has exactly numInputs inputs. // - the transaction has exactly numOutputs outputs. // - the transaction lock time is 0. -// - the transaction version is between 1 and maxTxVersion. +// - the transaction version is between minTxVersion and maxTxVersion. // - each input has a sequence number equal to MaxTxInSequenceNum. // - each input has an empty signature script. // - each input has an empty witness. func CheckPreSignedTxSanity( tx *wire.MsgTx, numInputs, numOutputs uint32, - maxTxVersion int32, + minTxVersion, maxTxVersion int32, ) error { if tx == nil { return fmt.Errorf("tx must not be nil") @@ -261,8 +261,8 @@ func CheckPreSignedTxSanity( return fmt.Errorf("pre-signed tx must not have locktime") } - if tx.Version > maxTxVersion || tx.Version < 1 { - return fmt.Errorf("tx version must be between 1 and %d", maxTxVersion) + if tx.Version > maxTxVersion || tx.Version < minTxVersion { + return fmt.Errorf("tx version must be between %d and %d", minTxVersion, maxTxVersion) } txWeight := blockchain.GetTransactionWeight(transaction) @@ -293,6 +293,8 @@ func CheckPreSignedUnbondingTxSanity(tx *wire.MsgTx) error { tx, 1, 1, + // Unbonding tx is always version 2 + MaxTxVersion, MaxTxVersion, ) } @@ -302,6 +304,8 @@ func CheckPreSignedSlashingTxSanity(tx *wire.MsgTx) error { tx, 1, 2, + // slashing tx version can be between 1 and 2 + 1, MaxTxVersion, ) } diff --git a/btcstaking/staking_test.go b/btcstaking/staking_test.go index b91265847..0f596915a 100644 --- a/btcstaking/staking_test.go +++ b/btcstaking/staking_test.go @@ -421,6 +421,7 @@ func TestCheckPreSignedTxSanity(t *testing.T) { genTx func() *wire.MsgTx numInputs uint32 numOutputs uint32 + minTxVersion int32 maxTxVersion int32 wantErr bool expectedErrMsg string @@ -435,9 +436,39 @@ func TestCheckPreSignedTxSanity(t *testing.T) { }, numInputs: 1, numOutputs: 1, + minTxVersion: 1, maxTxVersion: 2, wantErr: false, }, + { + name: "valid tx with required specific version 2", + genTx: func() *wire.MsgTx { + tx := wire.NewMsgTx(2) + tx.AddTxIn(wire.NewTxIn(wire.NewOutPoint(&chainhash.Hash{}, 0), nil, nil)) + tx.AddTxOut(wire.NewTxOut(1000, nil)) + return tx + }, + numInputs: 1, + numOutputs: 1, + minTxVersion: 2, + maxTxVersion: 2, + wantErr: false, + }, + { + name: "invalid tx when requireing specific version 2", + genTx: func() *wire.MsgTx { + tx := wire.NewMsgTx(3) + tx.AddTxIn(wire.NewTxIn(wire.NewOutPoint(&chainhash.Hash{}, 0), nil, nil)) + tx.AddTxOut(wire.NewTxOut(1000, nil)) + return tx + }, + numInputs: 1, + numOutputs: 1, + minTxVersion: 2, + maxTxVersion: 2, + wantErr: true, + expectedErrMsg: "tx version must be between 2 and 2", + }, { name: "non standard version tx", genTx: func() *wire.MsgTx { @@ -448,6 +479,7 @@ func TestCheckPreSignedTxSanity(t *testing.T) { }, numInputs: 1, numOutputs: 1, + minTxVersion: 1, maxTxVersion: 2, wantErr: true, expectedErrMsg: "tx version must be between 1 and 2", @@ -463,6 +495,7 @@ func TestCheckPreSignedTxSanity(t *testing.T) { }, numInputs: 1, numOutputs: 1, + minTxVersion: 1, maxTxVersion: 2, wantErr: true, expectedErrMsg: "pre-signed tx must not have locktime", @@ -478,6 +511,7 @@ func TestCheckPreSignedTxSanity(t *testing.T) { }, numInputs: 1, numOutputs: 1, + minTxVersion: 1, maxTxVersion: 2, wantErr: true, expectedErrMsg: "pre-signed tx must not have signature script", @@ -493,6 +527,7 @@ func TestCheckPreSignedTxSanity(t *testing.T) { }, numInputs: 1, numOutputs: 1, + minTxVersion: 1, maxTxVersion: 2, wantErr: true, expectedErrMsg: "tx must have exactly 1 inputs", @@ -508,6 +543,7 @@ func TestCheckPreSignedTxSanity(t *testing.T) { }, numInputs: 1, numOutputs: 1, + minTxVersion: 1, maxTxVersion: 2, wantErr: true, expectedErrMsg: "tx must have exactly 1 outputs", @@ -523,6 +559,7 @@ func TestCheckPreSignedTxSanity(t *testing.T) { }, numInputs: 1, numOutputs: 1, + minTxVersion: 1, maxTxVersion: 2, wantErr: true, expectedErrMsg: "pre-signed tx must not be replaceable", @@ -539,6 +576,7 @@ func TestCheckPreSignedTxSanity(t *testing.T) { }, numInputs: 1, numOutputs: 1, + minTxVersion: 1, maxTxVersion: 2, wantErr: true, expectedErrMsg: "tx weight must not exceed 400000", @@ -549,7 +587,7 @@ func TestCheckPreSignedTxSanity(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() err := btcstaking.CheckPreSignedTxSanity( - tt.genTx(), tt.numInputs, tt.numOutputs, tt.maxTxVersion, + tt.genTx(), tt.numInputs, tt.numOutputs, tt.minTxVersion, tt.maxTxVersion, ) if tt.wantErr {