Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
153 changes: 153 additions & 0 deletions packages/ripple-binary-codec/src/enums/definitions.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,26 @@
"type": "Amount"
}
],
[
"FeeAmount",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 32,
"type": "Amount"
}
],
[
"MaxFee",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 33,
"type": "Amount"
}
],
[
"LedgerEntryType",
{
Expand Down Expand Up @@ -850,6 +870,56 @@
"type": "UInt32"
}
],
[
"SponsorFlags",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 73,
"type": "UInt32"
}
],
[
"SponsoredOwnerCount",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 69,
"type": "UInt32"
}
],
[
"SponsoringOwnerCount",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 70,
"type": "UInt32"
}
],
[
"SponsoringAccountCount",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 71,
"type": "UInt32"
}
],
[
"ReserveCount",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 72,
"type": "UInt32"
}
],
[
"IndexNext",
{
Expand Down Expand Up @@ -1140,6 +1210,16 @@
"type": "UInt64"
}
],
[
"SponseeNode",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 32,
"type": "UInt64"
}
],
[
"EmailHash",
{
Expand Down Expand Up @@ -1510,6 +1590,16 @@
"type": "Hash256"
}
],
[
"ObjectID",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": false,
"nth": 39,
"type": "Hash256"
}
],
[
"hash",
{
Expand Down Expand Up @@ -2310,6 +2400,56 @@
"type": "AccountID"
}
],
[
"Sponsor",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": true,
"nth": 27,
"type": "AccountID"
}
],
[
"HighSponsor",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": true,
"nth": 28,
"type": "AccountID"
}
],
[
"LowSponsor",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": true,
"nth": 29,
"type": "AccountID"
}
],
[
"CounterpartySponsor",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": true,
"nth": 30,
"type": "AccountID"
}
],
[
"Sponsee",
{
"isSerialized": true,
"isSigningField": true,
"isVLEncoded": true,
"nth": 31,
"type": "AccountID"
}
],
[
"Number",
{
Expand Down Expand Up @@ -2840,6 +2980,16 @@
"type": "STObject"
}
],
[
"SponsorSignature",
{
"isSerialized": true,
"isSigningField": false,
"isVLEncoded": false,
"nth": 38,
"type": "STObject"
}
],
[
"Signers",
{
Expand Down Expand Up @@ -3459,6 +3609,7 @@
"PermissionedDomain": 130,
"RippleState": 114,
"SignerList": 83,
"Sponsorship": 135,
"Ticket": 84,
"Vault": 132,
"XChainOwnedClaimID": 113,
Expand Down Expand Up @@ -3720,6 +3871,8 @@
"SetFee": 101,
"SetRegularKey": 5,
"SignerListSet": 12,
"SponsorshipSet": 86,
"SponsorshipTransfer": 85,
"TicketCreate": 10,
"TrustSet": 20,
"UNLModify": 102,
Expand Down
21 changes: 11 additions & 10 deletions packages/ripple-keypairs/src/signing-schemes/secp256k1/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,17 @@ const secp256k1: SigningScheme = {
const normedPrivateKey =
privateKey.length === 66 ? privateKey.slice(2) : privateKey
return bytesToHex(
nobleSecp256k1.sign(Sha512.half(message), hexToBytes(normedPrivateKey), {
// "Canonical" signatures
lowS: true,
// Would fail tests if signatures aren't deterministic
extraEntropy: undefined,
format: 'der',
// We pass a pre-hashed message (Sha512Half), so disable secp256k1's
// default SHA-256 prehashing (added as default in @noble/curves 2.0.0)
prehash: false,
}),
nobleSecp256k1
.sign(Sha512.half(message), hexToBytes(normedPrivateKey), {
// "Canonical" signatures
lowS: true,
// Would fail tests if signatures aren't deterministic
extraEntropy: undefined,
// We pass a pre-hashed message (Sha512Half), so disable secp256k1's
// default SHA-256 prehashing (added as default in @noble/curves 2.0.0)
prehash: false,
})
.toBytes('der'),
).toUpperCase()
Comment on lines 45 to 57

@coderabbitai coderabbitai Bot Mar 30, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

What is the return type of secp256k1.sign() in @noble/curves when options are passed but no format is specified? Does the Signature object have toBytes or toDERRawBytes method?

💡 Result:

The return type of secp256k1.sign in @noble/curves, when options are passed but no format is specified, is a Signature object. This is evidenced by documentation examples where secp256k1.sign(msg, secretKey) without format returns a Signature instance, as shown in code snippets like const sigInstance = secp256k1.Signature.fromBytes(sigRec, 'recovered'); and historical notes that sign returns Signature with { r, s, recovery }. The default format when unspecified is 'compact' (64-byte RS), but the primary return is the Signature class instance. The Signature object has toCompactRawBytes and toDERRawBytes methods (or equivalent toBytes('compact')/'der' in some versions), as explicitly stated in interface definitions: interface ECDSASignature { r: bigint; s: bigint; recovery?: number; toCompactRawBytes: Uint8Array; toDERRawBytes: Uint8Array; }. Older versions used toBytes, but raw bytes methods are confirmed. It does not have a plain toBytes method without arguments based on available source snippets, but the queried methods exist.

Citations:


Build failure: toBytes is not the correct method for DER encoding.

In @noble/curves, secp256k1.sign() returns a Signature object. To export it as DER-encoded bytes, use .toDERRawBytes() instead of .toBytes('der'), which does not exist on the Signature class.

Fix
       return bytesToHex(
         nobleSecp256k1
           .sign(Sha512.half(message), hexToBytes(normedPrivateKey), {
             lowS: true,
             extraEntropy: undefined,
             prehash: false,
           })
-          .toBytes('der'),
+          .toDERRawBytes(),
       ).toUpperCase()
🧰 Tools
🪛 GitHub Actions: Node.js CI

[error] 56-56: TypeScript build failed in ripple-keypairs. TS2339: Property 'toBytes' does not exist on type 'Uint8Array'.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ripple-keypairs/src/signing-schemes/secp256k1/index.ts` around lines
45 - 57, The call to nobleSecp256k1.sign(...).toBytes('der') is invalid because
Signature objects use toDERRawBytes() for DER encoding; update the expression in
the signing function to call nobleSecp256k1.sign(Sha512.half(message),
hexToBytes(normedPrivateKey), {...}).toDERRawBytes(), then pass that result into
bytesToHex(...).toUpperCase() so the function continues returning the same hex
DER signature format.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This finding is based on an outdated version of the @noble/curves api. We are using version 2.x which includes a change from toDERRawBytes to toBytes('der').

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

},

Expand Down
6 changes: 6 additions & 0 deletions packages/xrpl/src/Wallet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -486,3 +486,9 @@ export {
signLoanSetByCounterparty,
combineLoanSetCounterpartySigners,
} from './counterpartySigner'

export {
signAsSponsor,
combineSponsorSigners,
addPreFundedSponsor,
} from './sponsorSigner'
Loading
Loading