Skip to content

Upstream backports - #1

Merged
gorunjinian merged 2 commits into
mainfrom
upstream-backports
Oct 9, 2026
Merged

gorunjinian merged 2 commits into
mainfrom
upstream-backports

Conversation

@gorunjinian

Copy link
Copy Markdown
Owner

No description provided.

…d script validation

- Reject extended keys whose decoded payload is not 78 bytes in `ExtendedPrivateKey.decode` and `ExtendedPublicKey.decode`, which previously zero-filled missing bytes and decoded a truncated xprv into a different, valid private key.
- Read the R and S lengths as unsigned bytes in `Crypto.isDERSignature`, so a length byte of 0x80 or more returns `false` instead of throwing `ArrayIndexOutOfBoundsException` (bitcoin-kmp #177).
- Replace `Crypto.decodeSignatureLax` with upstream's port of Bitcoin Core's `ecdsa_signature_parse_der_lax`, which bounds every length by the signature and returns an all-zero signature for malformed input, instead of allocating arrays of up to 2^31 bytes whose `OutOfMemoryError` escaped `Bip322.verifySimple` and `Psbt.extract`.
- Change `decodeSignatureLax` to take the DER bytes and return a `ByteVector64`, keeping the signatures of `der2compact` and `normalize`.
- Fix `OP_PUSHDATA.codeFromDataLength` to use `OP_PUSHDATA1` for 255-byte elements and `OP_PUSHDATA2` for 65535-byte elements, so scripts built by the library pass its own `SCRIPT_VERIFY_MINIMALDATA` check (bitcoin-kmp #191).
- Update `OP_PUSHDATA.isMinimal` to treat one-byte values 1 to 16 and 0x81 as never minimal, since they must be pushed with `OP_1` to `OP_16` and `OP_1NEGATE`.
- Replace the interpreter's IF/ELSE condition list with Bitcoin Core's constant-time `ConditionStack`, reducing the evaluation of a 300 KB tapscript nesting 100k `OP_IF` from 27.8s to 31ms (bitcoin-kmp #189, #196).
- Track the last executed `OP_CODESEPARATOR` by position instead of copying the remaining script each time it runs.
- Require the scriptSig of a P2SH-wrapped witness program to be exactly one push of the redeem script, as BIP-141 does, so `Psbt.extract` no longer approves malleated spends that the network rejects (bitcoin-kmp #191).
- Align the remaining interpreter rules with Bitcoin Core by failing cleanly on an empty P2WSH witness, checking an empty signature after the signature and public key encodings, treating `OP_CHECKLOCKTIMEVERIFY` and `OP_CHECKSEQUENCEVERIFY` as plain NOPs when their flag is unset, and requiring `SCRIPT_VERIFY_P2SH` whenever `SCRIPT_VERIFY_WITNESS` or `SCRIPT_VERIFY_CLEANSTACK` is set.
- Accept pay-to-anchor spends with any witness, since an empty witness is a standardness rule rather than a consensus rule (bitcoin-kmp #197).
- Set `MANDATORY_SCRIPT_VERIFY_FLAGS` to Bitcoin Core's consensus flags instead of `SCRIPT_VERIFY_P2SH` alone, add `MAX_SCRIPT_VERIFY_FLAGS`, and default `Script.Runner` to `STANDARD_SCRIPT_VERIFY_FLAGS`, whose value is unchanged.
- Reject non-canonical encodings in `BtcSerializer.varint`, as Bitcoin Core's `ReadCompactSize` does (bitcoin-kmp #198).
- Add regression tests for each fix, and confirm the ported interpreter passes Bitcoin Core's `script_tests.json`, `tx_valid.json`, `tx_invalid.json` and taproot functional test vectors.

Signed-off-by: Gorun Jinian <gorunbh@proton.me>
…s and add script interpreter alignment tests
@gorunjinian gorunjinian self-assigned this Oct 7, 2026
@gorunjinian
gorunjinian merged commit 6e508c5 into main Oct 9, 2026
1 check passed
@gorunjinian
gorunjinian deleted the upstream-backports branch October 9, 2026 04:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant