Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

psbt: always use non witness serialization format #1842

Merged
merged 1 commit into from
Apr 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 6 additions & 16 deletions btcutil/psbt/psbt.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,22 +214,12 @@ func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) {
return nil, err
}
msgTx := wire.NewMsgTx(2)
err = msgTx.Deserialize(bytes.NewReader(value))

// BIP-0174 states: "The transaction must be in the old serialization
// format (without witnesses)."
err = msgTx.DeserializeNoWitness(bytes.NewReader(value))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we continue to try to decode the witness version and fall back to non-witness? Since it's possible there's old software out there encoding wit the witness version, we'd potentially break compatibility across lnd version for even btcutil versions with this change as is.

It seems the most important thing here is for us to encode using the new witness version, AFAICT. So if we just serialize w/o the witness, then things are compatible across the prior versions.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can add the fallback. Though I don't think this change will create a compatibility issue. A PSBT packet with an unsigned TX that has a witness set cannot be serialized, the library will complain. And if you call msgTx.Serialize() with a transaction that has no witness, the old format will be used. Therefore the change to the serialization is purely to be more explicit about it. The actual important change is that we always read the TX expecting it to be in the non-witness format.

if err != nil {
// If there are no inputs in this yet incomplete transaction,
// the wire package still incorrectly assumes it's encoded in
// the witness format. We can fix this by just trying the non-
// witness encoding too. If that also fails, it's probably an
// invalid transaction.
msgTx = wire.NewMsgTx(2)
err2 := msgTx.DeserializeNoWitness(bytes.NewReader(value))

// If the second attempt also failed, something else is wrong
// and it probably makes more sense to return the original
// error instead of the error from the workaround.
if err2 != nil {
return nil, err
}
return nil, err
}
if !validateUnsignedTX(msgTx) {
return nil, ErrInvalidRawTxSigned
Expand Down Expand Up @@ -320,7 +310,7 @@ func (p *Packet) Serialize(w io.Writer) error {
serializedTx := bytes.NewBuffer(
make([]byte, 0, p.UnsignedTx.SerializeSize()),
)
if err := p.UnsignedTx.Serialize(serializedTx); err != nil {
if err := p.UnsignedTx.SerializeNoWitness(serializedTx); err != nil {
return err
}

Expand Down
7 changes: 4 additions & 3 deletions btcutil/psbt/psbt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ var validPsbtHex = map[int]string{
4: "70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000",
5: "70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000a0f0102030405060708090f0102030405060708090a0b0c0d0e0f0000",
6: "70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000002206030d097466b7f59162ac4d90bf65f2a31a8bad82fcd22e98138dcf279401939bd104ffffffff0a0f0102030405060708090f0102030405060708090a0b0c0d0e0f0000",
7: "70736274ff01002001000000000100000000000000000d6a0b68656c6c6f20776f726c64000000000000",
}

// These are all invalid PSBTs for the indicated
Expand Down Expand Up @@ -115,7 +116,7 @@ var invalidPsbtHex = map[int]string{
// This tests that valid PSBT serializations can be parsed
// into Psbt structs.
func TestReadValidPsbtAndReserialize(t *testing.T) {
for _, v := range validPsbtHex {
for key, v := range validPsbtHex {
PsbtBytes, err := hex.DecodeString(v)
if err != nil {
t.Fatalf("Unable to decode hex: %v", err)
Expand All @@ -128,8 +129,8 @@ func TestReadValidPsbtAndReserialize(t *testing.T) {
t.Fatalf("unable to parse psbt: %v", err)
}

t.Logf("Successfully parsed test, got transaction: %v",
spew.Sdump(testPsbt.UnsignedTx))
t.Logf("Successfully parsed test %d, got transaction: %v",
key, spew.Sdump(testPsbt.UnsignedTx))

var b bytes.Buffer
err = testPsbt.Serialize(&b)
Expand Down