All files / src/util div.ts

95.45% Statements 42/44
66.66% Branches 2/3
100% Functions 1/1
95.45% Lines 42/44

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 451x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 8665x 8665x 8665x 8665x 8665x 8665x 8665x 8161x 8161x 8161x 8161x 8161x     8161x 8161x 8161x 8161x 8665x 8665x 8665x 8665x 8665x 8665x 8665x 8665x 8665x 8665x 8665x 8665x 8665x  
import { Field, Provable, UInt64, Gadgets, Struct } from "o1js";
 
export class MulDivResult extends Struct({
  result: UInt64,
  remainder: UInt64,
}) {}
 
class MulDivResultInternal extends Struct({
  result: Field,
  remainder: Field,
}) {}
 
export function mulDiv(params: {
  value: UInt64;
  multiplier: UInt64;
  denominator: UInt64;
}): MulDivResult {
  const { value, multiplier, denominator } = params;
  denominator.equals(UInt64.zero).assertFalse("division by zero"); // should fail in case the denominator is zero
  const fields = Provable.witness(MulDivResultInternal, () => {
    const valueBigInt = value.toBigInt();
    const multiplierBigInt = multiplier.toBigInt();
    const denominatorBigInt = denominator.toBigInt();
    // handle division by zero for first pass of the prover that can pass zero instead of the real value
    if (denominatorBigInt === 0n) {
      return { result: Field.from(0n), remainder: Field.from(0n) };
    }
    const result = (valueBigInt * multiplierBigInt) / denominatorBigInt;
    const remainder =
      valueBigInt * multiplierBigInt - result * denominatorBigInt;
    return { result: Field.from(result), remainder: Field.from(remainder) };
  });
  Gadgets.rangeCheck64(fields.result);
  Gadgets.rangeCheck64(fields.remainder);
  fields.remainder.assertLessThan(denominator.value); // should fail in case the denominator is zero
  fields.result
    .mul(denominator.value)
    .add(fields.remainder)
    .assertEquals(value.value.mul(multiplier.value)); // should fail in case the denominator is zero
  return {
    result: UInt64.Unsafe.fromField(fields.result),
    remainder: UInt64.Unsafe.fromField(fields.remainder),
  };
}