JubJubAffineNativePoint.fromBytes constructor

JubJubAffineNativePoint.fromBytes(
  1. List<int> bytes, {
  2. bool zip216Enabled = false,
})

Implementation

factory JubJubAffineNativePoint.fromBytes(
  List<int> bytes, {
  bool zip216Enabled = false,
}) {
  final b =
      bytes
          .exc(
            length: 32,
            operation: "fromBytes",
            reason: "Invalid point encoding bytes length.",
          )
          .clone();
  // Grab the sign bit
  final sign = (b[31] >> 7).toU8;

  // Mask away the sign bit
  b[31] &= 0x7F;

  // Interpret remaining bytes as v-coordinate
  final v = JubJubNativeFq.fromBytes(b);
  final v2 = v.square();

  // u^2 = (v^2 - 1) / (1 + d*v^2)
  final denominator = (JubJubNativeFq.one() + JubJubNativeFq.edwardsD() * v2);
  JubJubNativeFq invDenominator =
      denominator.invert() ?? JubJubNativeFq.zero();
  final u2 = (v2 - JubJubNativeFq.one()) * invDenominator;
  final u = u2.sqrt().sqrtOrNull();
  if (u == null) {
    throw ArgumentException.invalidOperationArguments(
      "JubJubAffinePoint",
      reason: "Invalid point encoding bytes.",
    );
  }

  // Fix the sign of u if necessary
  final flipSign = ((u.toBytes()[0] ^ sign) & 1) == 1;
  final finalU = flipSign ? -u : u;

  final uIsZero = u.isZero();

  // ZIP 216 check: reject encoding if enabled and u == 0 and flipSign == true
  final isValid = !(zip216Enabled && uIsZero && flipSign);
  if (!isValid) {
    throw ArgumentException.invalidOperationArguments(
      "JubJubAffinePoint",
      reason: "Invalid point encoding bytes.",
    );
  }
  return JubJubAffineNativePoint(u: finalU, v: v);
}