Conversation
Add Keccak-256, ECDSA support, and tests Bump package to v1.11.0-rc.5 and add a native Keccak-256 implementation and test suite. Export keccak helpers from runtime/index and add keccak256, keccak256Concat, functionSelector, ethAddressFromPubKey, and low-level rot64 utilities. Extend signature handling: add ECDSA to SignaturesMethods, introduce verifyECDSASignature/internalVerifyECDSA and secp256k1 public-key validation, and update Blockchain.verifySignature to accept an explicit signatureType (with consensus checks, deprecation warnings, and error handling). Small API/behavior change in ExtendedAddress: use Revert for tweakedPublicKey validation. Includes comprehensive as-pect tests for keccak256 and rotation helpers.
Introduce ECDSA sub-type and key-format discriminants and update verification plumbing. Rework Signatures enum and add ECDSASubType and ECDSAKeyFormat to support Ethereum (ecrecover, 65-byte) and Bitcoin (direct verify, 64-byte) verification models. Verify methods: verifyECDSASignature now delegates as Ethereum subtype; added verifyBitcoinECDSASignature (deprecated) for direct-verify flow. internalVerifyECDSA now accepts a subType, validates signature length per sub-type, encodes type/subtype/format into the host buffer, and enforces 32-byte hashes. validateSecp256k1PublicKey expanded to accept 33 (compressed), 64 (raw X||Y), 65 (uncompressed/hybrid) formats and improved error messages. Also fix consensus check logic to reject ECDSA when unsafe signatures are not allowed and add deprecation warnings advising use of consensus-aware verifySignature().
There was a problem hiding this comment.
Pull request overview
This PR introduces Keccak-256 hashing utilities and expands signature verification plumbing to support ECDSA (with Ethereum vs Bitcoin verification sub-types) alongside existing Schnorr/ML-DSA consensus-aware verification.
Changes:
- Add a pure AssemblyScript Keccak-256 implementation (+ helper utilities) and a comprehensive as-pect test suite.
- Rework signature method discriminants and add ECDSA sub-type/key-format tagging for host verification.
- Update
BlockchainEnvironmentverification methods to handle ECDSA flows and tighten consensus gating; adjustExtendedAddressto throwRevertfor invalid key sizes.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/keccak256.spec.ts | Adds Keccak-256 test vectors, boundary/edge tests, and rotation helper coverage. |
| runtime/hashing/keccak256.ts | Implements Keccak-256 + helpers (keccak256Concat, functionSelector, ethAddressFromPubKey, rotations). |
| runtime/index.ts | Exposes Keccak hashing utilities via the public runtime entrypoint. |
| runtime/env/consensus/Signatures.ts | Redefines signature discriminants and introduces ECDSA subtype/key-format enums. |
| runtime/env/BlockchainEnvironment.ts | Adds ECDSA verification methods and updates consensus-aware verifySignature control flow. |
| runtime/types/ExtendedAddress.ts | Switches invalid tweaked key length from Error to Revert. |
| package.json | Bumps package version to 1.11.0-rc.5. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| * Host buffer layout: [type(1), subtype(1), ...pubkey_material] | ||
| * type = SignaturesMethods.ECDSA (0x00) | ||
| * subtype = ECDSASubType.Ethereum (0x00) or ECDSASubType.Bitcoin (0x01) |
There was a problem hiding this comment.
The doc comment for the ECDSA host buffer layout says [type(1), subtype(1), ...pubkey_material], but the implementation actually writes three header bytes (type, subtype, formatTag) before the pubkey. Please update the comment to reflect the real buffer layout so host/SDK implementers don’t miss the format byte.
| * Host buffer layout: [type(1), subtype(1), ...pubkey_material] | |
| * type = SignaturesMethods.ECDSA (0x00) | |
| * subtype = ECDSASubType.Ethereum (0x00) or ECDSASubType.Bitcoin (0x01) | |
| * Host buffer layout: [type(1), subtype(1), format(1), ...pubkey_material] | |
| * type = SignaturesMethods.ECDSA (0x00) | |
| * subtype = ECDSASubType.Ethereum (0x00) or ECDSASubType.Bitcoin (0x01) | |
| * format = ECDSAKeyFormat tag describing the public key encoding |
| ERROR( | ||
| `Please consider migrating to a more secure, quantum-resistant signature scheme like ML-DSA as ECDSA signatures are vulnerable to quantum attacks. You may still use this via Blockchain.verifyECDSASignature() if needed, but it is not recommended for long-term security.`, |
There was a problem hiding this comment.
verifySignature() now accepts signatureType: SignaturesMethods, but the ECDSA branch only emits an ERROR(...) message and then falls through to the generic Revert at the end, so callers can’t actually request ECDSA verification here. Since this method takes an ExtendedAddress (not an ECDSA public key), it would be clearer to explicitly reject SignaturesMethods.ECDSA with a direct Revert that points to verifyECDSASignature() / verifyBitcoinECDSASignature(), and keep the parameter semantics focused on Schnorr vs ML-DSA (or revert back to a forceMLDSA flag).
| ERROR( | |
| `Please consider migrating to a more secure, quantum-resistant signature scheme like ML-DSA as ECDSA signatures are vulnerable to quantum attacks. You may still use this via Blockchain.verifyECDSASignature() if needed, but it is not recommended for long-term security.`, | |
| throw new Revert( | |
| 'ECDSA verification is not supported by Blockchain.verifySignature(); use Blockchain.verifyECDSASignature() or Blockchain.verifyBitcoinECDSASignature() instead.', |
| /** | ||
| * Compute Ethereum-style address from uncompressed public key. | ||
| * address = keccak256(pubkey)[12:32] | ||
| * | ||
| * @param publicKey - 64-byte uncompressed public key (without 0x04 prefix) | ||
| * @returns 20-byte Ethereum address as Uint8Array | ||
| */ | ||
| export function ethAddressFromPubKey(publicKey: Uint8Array): Uint8Array { | ||
| const hash = keccak256(publicKey); | ||
| const addr = new Uint8Array(20); | ||
| for (let i: i32 = 0; i < 20; i++) { | ||
| addr[i] = hash[12 + i]; | ||
| } | ||
| return addr; |
There was a problem hiding this comment.
ethAddressFromPubKey() documents publicKey as a 64-byte uncompressed key (X||Y without 0x04), but it doesn’t validate the input length. As a public API this can silently produce incorrect addresses if callers pass a 33/65-byte SEC1 key by mistake; consider enforcing publicKey.length === 64 (and throwing/reverting with a clear message) to prevent misuse.
Replace the boolean forceMLDSA parameter in docs/examples with a SignaturesMethods enum (SignaturesMethods.Schnorr / SignaturesMethods.MLDSA) and update all sample code to import and use it. Add documentation for deprecated ECDSA verification (Ethereum ecrecover and Bitcoin direct models) gated by the UNSAFE_QUANTUM_SIGNATURES_ALLOWED flag, plus new API entries for verifyECDSASignature and verifyBitcoinECDSASignature. Document built-in Ethereum-compatible Keccak-256 helpers (keccak256, keccak256Concat, functionSelector, ethAddressFromPubKey) and update capability matrices, diagrams, and examples to reflect support, deprecation notices, and consensus-aware behavior.
Description
Introduce ECDSA sub-type and key-format discriminants and update verification plumbing. Rework Signatures enum and add ECDSASubType and ECDSAKeyFormat to support Ethereum (ecrecover, 65-byte) and Bitcoin (direct verify, 64-byte) verification models. Verify methods: verifyECDSASignature now delegates as Ethereum subtype; added verifyBitcoinECDSASignature (deprecated) for direct-verify flow. internalVerifyECDSA now accepts a subType, validates signature length per sub-type, encodes type/subtype/format into the host buffer, and enforces 32-byte hashes. validateSecp256k1PublicKey expanded to accept 33 (compressed), 64 (raw X||Y), 65 (uncompressed/hybrid) formats and improved error messages. Also fix consensus check logic to reject ECDSA when unsafe signatures are not allowed and add deprecation warnings advising use of consensus-aware verifySignature().
Type of Change
Checklist
Build & Tests
npm installcompletes without errorsnpm testpasses all testsCode Quality
Documentation
Security
OPNet Specific
Testing
Related Issues
By submitting this PR, I confirm that my contribution is made under the terms of the project's license.