Skip to content

Commit c4d9112

Browse files
committed
psbt: add comprehensive PSBTv2 BIP-370 compliance tests
- Add TestPSBTv2DetermineLockTimeAlgorithm covering all BIP-370 cases: * Height-based preference when both types supported * Conflict detection for incompatible input requirements * Fallback locktime usage when no input constraints - Add TestPSBTv2AddUnknownFields for unknown field handling - Ensures PSBTv2 implementation fully complies with BIP-370 spec These tests validate the core functionality added in previous commits.
1 parent 617e145 commit c4d9112

1 file changed

Lines changed: 85 additions & 0 deletions

File tree

btcutil/psbt/psbt_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,3 +1850,88 @@ func TestPsbtV2Locktimes(t *testing.T) {
18501850
// Test modifiability flag.
18511851
require.Equal(t, uint8(0x01), p.TxModifiable)
18521852
}
1853+
1854+
// TestPSBTv2DetermineLockTimeAlgorithm tests the comprehensive BIP-370 lock time determination algorithm
1855+
func TestPSBTv2DetermineLockTimeAlgorithm(t *testing.T) {
1856+
t.Run("Height-based preference when both supported (BIP-370 tie-breaker)", func(t *testing.T) {
1857+
p, err := NewV2(2, 100000, 0)
1858+
require.NoError(t, err)
1859+
1860+
txid, _ := chainhash.NewHashFromStr("1111111111111111111111111111111111111111111111111111111111111111")
1861+
1862+
// Input 1: Both time and height (flexible)
1863+
p.AddInput(*wire.NewOutPoint(txid, 0), 0)
1864+
p.Inputs[0].TimeLocktime = 1600000000
1865+
p.Inputs[0].HeightLocktime = 550000
1866+
1867+
// Input 2: Both time and height (flexible)
1868+
p.AddInput(*wire.NewOutPoint(txid, 1), 0)
1869+
p.Inputs[1].TimeLocktime = 1650000000
1870+
p.Inputs[1].HeightLocktime = 600000
1871+
1872+
// BIP-370: "height-based must be chosen" when both supported
1873+
lockTime, err := p.DetermineLockTime()
1874+
require.NoError(t, err)
1875+
require.Equal(t, uint32(600000), lockTime) // Max height, NOT max time
1876+
})
1877+
1878+
t.Run("Conflicting requirements should error", func(t *testing.T) {
1879+
p, err := NewV2(2, 0, 0)
1880+
require.NoError(t, err)
1881+
1882+
txid, _ := chainhash.NewHashFromStr("2222222222222222222222222222222222222222222222222222222222222222")
1883+
1884+
// Input 1: Time-only (cannot satisfy height)
1885+
p.AddInput(*wire.NewOutPoint(txid, 0), 0)
1886+
p.Inputs[0].TimeLocktime = 1600000000
1887+
1888+
// Input 2: Height-only (cannot satisfy time)
1889+
p.AddInput(*wire.NewOutPoint(txid, 1), 0)
1890+
p.Inputs[1].HeightLocktime = 500000
1891+
1892+
// Should fail - conflicting requirements
1893+
_, err = p.DetermineLockTime()
1894+
require.Error(t, err)
1895+
require.Equal(t, ErrInvalidPsbtFormat, err)
1896+
})
1897+
1898+
t.Run("Fallback locktime when no constraints", func(t *testing.T) {
1899+
fallback := uint32(123456)
1900+
p, err := NewV2(2, fallback, 0)
1901+
require.NoError(t, err)
1902+
1903+
txid, _ := chainhash.NewHashFromStr("3333333333333333333333333333333333333333333333333333333333333333")
1904+
p.AddInput(*wire.NewOutPoint(txid, 0), 0)
1905+
// No TimeLocktime or HeightLocktime set
1906+
1907+
lockTime, err := p.DetermineLockTime()
1908+
require.NoError(t, err)
1909+
require.Equal(t, fallback, lockTime)
1910+
})
1911+
}
1912+
1913+
// TestPSBTv2AddUnknownFields tests the addUnknown field handling
1914+
func TestPSBTv2AddUnknownFields(t *testing.T) {
1915+
p, err := NewV2(2, 0, 0)
1916+
require.NoError(t, err)
1917+
1918+
txid, _ := chainhash.NewHashFromStr("4444444444444444444444444444444444444444444444444444444444444444")
1919+
p.AddInput(*wire.NewOutPoint(txid, 0), 0)
1920+
1921+
// Test adding unknown field succeeds
1922+
err = p.Inputs[0].addUnknown(0xfc, []byte{0x01, 0x02}, []byte{0x03, 0x04})
1923+
require.NoError(t, err)
1924+
require.Len(t, p.Inputs[0].Unknowns, 1)
1925+
1926+
// Test duplicate detection
1927+
err = p.Inputs[0].addUnknown(0xfc, []byte{0x01, 0x02}, []byte{0x03, 0x04})
1928+
require.Error(t, err)
1929+
require.Equal(t, ErrDuplicateKey, err)
1930+
1931+
p.AddOutput(1000000, []byte{0x76, 0xa9, 0x14})
1932+
1933+
// Test output unknown fields
1934+
err = p.Outputs[0].addUnknown(0xfd, []byte{0x05}, []byte{0x06})
1935+
require.NoError(t, err)
1936+
require.Len(t, p.Outputs[0].Unknowns, 1)
1937+
}

0 commit comments

Comments
 (0)