Documentation Index Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
Use this file to discover all available pages before exploring further.
Try it Live Run Signature examples in the interactive playground
Utilities
Helper functions for signature operations.
getAlgorithm
Get signature algorithm.
Signature
function getAlgorithm ( signature : BrandedSignature ) : SignatureAlgorithm
Parameters
signature - BrandedSignature
Returns
SignatureAlgorithm ("secp256k1" | "p256" | "ed25519")
Example
const sig = Signature . fromSecp256k1 ( r , s , 27 );
console . log ( Signature . getAlgorithm ( sig )); // "secp256k1"
const p256Sig = Signature . fromP256 ( r , s );
console . log ( Signature . getAlgorithm ( p256Sig )); // "p256"
const ed25519Sig = Signature . fromEd25519 ( bytes );
console . log ( Signature . getAlgorithm ( ed25519Sig )); // "ed25519"
getR
Extract r component from ECDSA signature.
Signature
function getR ( signature : BrandedSignature ) : Uint8Array
Parameters
signature - ECDSA BrandedSignature
Returns
Uint8Array (32 bytes) - r component
Throws
Error if signature is Ed25519 (no r component)
Example
const sig = Signature . fromSecp256k1 ( r , s , 27 );
const rComponent = Signature . getR ( sig );
console . log ( rComponent . length ); // 32
console . log ( rComponent . every (( b , i ) => b === r [ i ])); // true
// Ed25519 throws
const ed25519Sig = Signature . fromEd25519 ( bytes );
try {
Signature . getR ( ed25519Sig ); // Throws
} catch ( err ) {
console . error ( 'Ed25519 has no r component' );
}
getS
Extract s component from ECDSA signature.
Signature
function getS ( signature : BrandedSignature ) : Uint8Array
Parameters
signature - ECDSA BrandedSignature
Returns
Uint8Array (32 bytes) - s component
Throws
Error if signature is Ed25519 (no s component)
Example
const sig = Signature . fromSecp256k1 ( r , s , 27 );
const sComponent = Signature . getS ( sig );
console . log ( sComponent . length ); // 32
console . log ( sComponent . every (( b , i ) => b === s [ i ])); // true
// Check canonicality of s
const SECP256K1_N_DIV_2 = new Uint8Array ([
0x7f , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0x5d , 0x57 , 0x6e , 0x73 , 0x57 , 0xa4 , 0x50 , 0x1d ,
0xdf , 0xe9 , 0x2f , 0x46 , 0x68 , 0x1b , 0x20 , 0xa0 ,
]);
function isLowS ( sig : BrandedSignature ) : boolean {
const s = Signature . getS ( sig );
for ( let i = 0 ; i < 32 ; i ++ ) {
if ( s [ i ] ! < SECP256K1_N_DIV_2 [ i ] ! ) return true ;
if ( s [ i ] ! > SECP256K1_N_DIV_2 [ i ] ! ) return false ;
}
return true ;
}
getV
Get recovery ID from secp256k1 signature.
Signature
function getV ( signature : BrandedSignature ) : number | undefined
Parameters
signature - BrandedSignature
Returns
number (27 or 28) - Recovery ID if present
undefined - If not secp256k1 or v not set
Example
// With recovery ID
const sig1 = Signature . fromSecp256k1 ( r , s , 27 );
console . log ( Signature . getV ( sig1 )); // 27
// Without recovery ID
const sig2 = Signature . fromSecp256k1 ( r , s );
console . log ( Signature . getV ( sig2 )); // undefined
// P-256 has no v
const sig3 = Signature . fromP256 ( r , s );
console . log ( Signature . getV ( sig3 )); // undefined
// Ed25519 has no v
const sig4 = Signature . fromEd25519 ( bytes );
console . log ( Signature . getV ( sig4 )); // undefined
Use Cases
// Ethereum address recovery
function recoverAddress (
message : Uint8Array ,
sig : BrandedSignature
) : Address {
const v = Signature . getV ( sig );
if ( v === undefined ) {
throw new Error ( 'Recovery ID required' );
}
const r = Signature . getR ( sig );
const s = Signature . getS ( sig );
// Use crypto module for actual recovery
return recoverPublicKey ( message , r , s , v );
}
// EIP-155 transaction encoding
function encodeTransaction ( tx : Transaction , sig : BrandedSignature ) : Uint8Array {
const v = Signature . getV ( sig );
const eip155V = tx . chainId * 2 + 35 + ( v ! - 27 );
return RLP . encode ([
tx . nonce ,
tx . gasPrice ,
tx . gasLimit ,
tx . to ,
tx . value ,
tx . data ,
eip155V ,
Signature . getR ( sig ),
Signature . getS ( sig ),
]);
}
Comparison
equals
Compare signatures for equality.
Signature
function equals (
a : BrandedSignature ,
b : BrandedSignature
) : boolean
Parameters
a - First signature
b - Second signature
Returns
true if signatures are equal (algorithm, bytes, and v match)
Example
const sig1 = Signature . fromSecp256k1 ( r , s , 27 );
const sig2 = Signature . fromSecp256k1 ( r , s , 27 );
const sig3 = Signature . fromSecp256k1 ( r , s , 28 );
console . log ( Signature . equals ( sig1 , sig2 )); // true
console . log ( Signature . equals ( sig1 , sig3 )); // false (different v)
// Different algorithms
const p256Sig = Signature . fromP256 ( r , s );
console . log ( Signature . equals ( sig1 , p256Sig )); // false
Implementation
Checks:
Algorithm match
Byte-by-byte comparison
Recovery ID match (if present)
// Constant-time byte comparison
function equals ( a : BrandedSignature , b : BrandedSignature ) : boolean {
if ( a . algorithm !== b . algorithm ) return false ;
if ( a . length !== b . length ) return false ;
if ( a . v !== b . v ) return false ;
let result = 0 ;
for ( let i = 0 ; i < a . length ; i ++ ) {
result |= a [ i ] ! ^ b [ i ] ! ;
}
return result === 0 ;
}
Type guard for BrandedSignature.
Signature
function is ( value : unknown ) : value is BrandedSignature
Parameters
Returns
true if value is BrandedSignature
Example
const sig = Signature . fromSecp256k1 ( r , s , 27 );
console . log ( Signature . is ( sig )); // true
const bytes = Bytes64 ();
console . log ( Signature . is ( bytes )); // false
const obj = { algorithm: 'secp256k1' };
console . log ( Signature . is ( obj )); // false
// Type narrowing
function process ( value : unknown ) {
if ( Signature . is ( value )) {
// value is BrandedSignature
console . log ( value . algorithm );
}
}
Checks
Is object
Is Uint8Array instance
Has [brand] === "Signature"
Has algorithm property
Verification (Placeholder)
verify
Verify signature against message and public key.
Signature
function verify (
signature : BrandedSignature ,
message : Uint8Array ,
publicKey : Uint8Array
) : boolean
Parameters
signature - Signature to verify
message - Message that was signed
publicKey - Public key to verify against
Returns
true if signature is valid
Throws
InvalidAlgorithmError - Always (placeholder implementation)
Example
const sig = Signature . fromSecp256k1 ( r , s , 27 );
try {
const valid = Signature . verify ( sig , message , publicKey );
} catch ( err ) {
console . error ( err . message );
// "Signature verification for secp256k1 requires integration with crypto primitives"
}
Note
This is a placeholder. Actual verification requires crypto module integration:
// Use crypto module instead
import { secp256k1 } from '@voltaire/crypto' ;
function verifySecp256k1 (
sig : BrandedSignature ,
message : Uint8Array ,
publicKey : Uint8Array
) : boolean {
const r = Signature . getR ( sig );
const s = Signature . getS ( sig );
return secp256k1 . verify ( message , r , s , publicKey );
}
Helper Functions
Component Comparison
// Compare r components
function compareR ( a : BrandedSignature , b : BrandedSignature ) : boolean {
const rA = Signature . getR ( a );
const rB = Signature . getR ( b );
return rA . every (( byte , i ) => byte === rB [ i ]);
}
// Compare s components
function compareS ( a : BrandedSignature , b : BrandedSignature ) : boolean {
const sA = Signature . getS ( a );
const sB = Signature . getS ( b );
return sA . every (( byte , i ) => byte === sB [ i ]);
}
Algorithm Detection
function isECDSA ( sig : BrandedSignature ) : boolean {
return sig . algorithm === 'secp256k1' || sig . algorithm === 'p256' ;
}
function isEdDSA ( sig : BrandedSignature ) : boolean {
return sig . algorithm === 'ed25519' ;
}
function hasRecoveryId ( sig : BrandedSignature ) : boolean {
return sig . v !== undefined ;
}
// Extract both r and s
function getComponents ( sig : BrandedSignature ) : {
r : Uint8Array ;
s : Uint8Array ;
} {
return {
r: Signature . getR ( sig ),
s: Signature . getS ( sig ),
};
}
// Extract all metadata
function getMetadata ( sig : BrandedSignature ) : {
algorithm : SignatureAlgorithm ;
v ?: number ;
length : number ;
} {
return {
algorithm: Signature . getAlgorithm ( sig ),
v: Signature . getV ( sig ),
length: sig . length ,
};
}
Display Helpers
function formatSignature ( sig : BrandedSignature ) : string {
const r = Signature . getR ( sig );
const s = Signature . getS ( sig );
const v = Signature . getV ( sig );
return [
`Algorithm: ${ sig . algorithm } ` ,
`r: 0x ${ Hex ( r ) } ` ,
`s: 0x ${ Hex ( s ) } ` ,
v !== undefined ? `v: ${ v } ` : null ,
]. filter ( Boolean ). join ( ' \n ' );
}
console . log ( formatSignature ( sig ));
// Algorithm: secp256k1
// r: 0x1234...
// s: 0x5678...
// v: 27
Validation Helpers
// Check if signature has expected algorithm
function assertAlgorithm (
sig : BrandedSignature ,
expected : SignatureAlgorithm
) : void {
const actual = Signature . getAlgorithm ( sig );
if ( actual !== expected ) {
throw new Error ( `Expected ${ expected } , got ${ actual } ` );
}
}
// Check if signature has recovery ID
function assertRecoveryId ( sig : BrandedSignature ) : void {
if ( Signature . getV ( sig ) === undefined ) {
throw new Error ( 'Recovery ID required' );
}
}
// Usage
assertAlgorithm ( sig , 'secp256k1' );
assertRecoveryId ( sig );
Component Access
// Efficient: direct property access
const algorithm = sig . algorithm ; // O(1)
const v = sig . v ; // O(1)
// Efficient: slice creates view (no copy)
const r = sig . slice ( 0 , 32 ); // O(1) view creation
const s = sig . slice ( 32 , 64 ); // O(1) view creation
// Less efficient: helper functions have call overhead
const r2 = Signature . getR ( sig ); // O(1) + function call
Equality Comparison
// Constant-time comparison (security)
Signature . equals ( sig1 , sig2 ); // O(n), constant-time
// Fast but not constant-time
function fastEquals ( a : BrandedSignature , b : BrandedSignature ) : boolean {
if ( a . algorithm !== b . algorithm ) return false ;
if ( a . v !== b . v ) return false ;
return a . every (( byte , i ) => byte === b [ i ]); // Early exit
}
Type Checking
// Fast runtime check
Signature . is ( value ); // O(1)
// Use for validation at API boundaries
function acceptSignature ( value : unknown ) : BrandedSignature {
if ( ! Signature . is ( value )) {
throw new TypeError ( 'Expected BrandedSignature' );
}
return value ;
}
Common Patterns
Decompose Signature
function decomposeSignature ( sig : BrandedSignature ) {
return {
algorithm: Signature . getAlgorithm ( sig ),
r: Signature . getR ( sig ),
s: Signature . getS ( sig ),
v: Signature . getV ( sig ),
};
}
const { algorithm , r , s , v } = decomposeSignature ( sig );
Clone Signature
function cloneSignature ( sig : BrandedSignature ) : BrandedSignature {
const algorithm = Signature . getAlgorithm ( sig );
switch ( algorithm ) {
case 'secp256k1' :
return Signature . fromSecp256k1 (
Signature . getR ( sig ),
Signature . getS ( sig ),
Signature . getV ( sig )
);
case 'p256' :
return Signature . fromP256 (
Signature . getR ( sig ),
Signature . getS ( sig )
);
case 'ed25519' :
return Signature . fromEd25519 ( sig . slice ());
}
}
Signature Info
function getSignatureInfo ( sig : BrandedSignature ) : string {
const algorithm = Signature . getAlgorithm ( sig );
const v = Signature . getV ( sig );
return ` ${ algorithm }${ v !== undefined ? ` (v= ${ v } )` : '' } ` ;
}
console . log ( getSignatureInfo ( sig )); // "secp256k1 (v=27)"
See Also