Class VoucherCanonicalBytes

java.lang.Object
xyz.tcheeric.cashu.voucher.domain.VoucherCanonicalBytes

public final class VoucherCanonicalBytes extends Object
Renders the exact bytes an issuer signature commits to.

This is the single definition of the voucher signing preimage. It is deliberately its own class rather than a detail of VoucherSignatureService: the bytes are a wire contract shared with every verifier, including the offline TypeScript wallet, so anything that needs to reproduce them must be able to call the one implementation instead of copying it.

The form is ["VOUCHER", "data_hex", "nonce", [[tag, value...], ...]], matching WellKnownSecretSerializer, with issuer_sig and issuer_pubkey omitted because they are only added after signing.

Why the tag key decides what is numeric

NUT-10 carries every tag value as a string, so the runtime type of a value says nothing about how it was written when a signature was made. An earlier version keyed off value instanceof Number; when cashu-lib began modelling tag values as String, every numeric tag silently changed from 1000 to "1000" and every voucher signature ever issued would have stopped verifying. The voucher tag schema is fixed and known, so the key is the durable record of which values are numbers.

See Also:
  • Method Details

    • of

      public static byte[] of(@NonNull @NonNull xyz.tcheeric.cashu.common.nut18.VoucherSecret secret)
      Renders the canonical signing bytes for a voucher secret.
      Parameters:
      secret - the voucher secret to render
      Returns:
      the bytes that are hashed and signed
    • of

      public static byte[] of(@NonNull @NonNull xyz.tcheeric.cashu.common.nut18.VoucherSecret secret, @NonNull @NonNull VoucherCanonicalBytes.NumericTagForm numericForm)
      Renders the canonical signing bytes, choosing how numeric values are written.
      Parameters:
      secret - the voucher secret to render
      numericForm - the rendering of numeric tag values
      Returns:
      the bytes that are hashed and signed