Skip to content

Commit

Permalink
Merge pull request #1438 from julio4/feat/safe-int
Browse files Browse the repository at this point in the history
Ensure safe Uint64/32 instanciations, with new Unsafe.fromField()
  • Loading branch information
mitschabaude authored Mar 7, 2024
2 parents 61fea3b + 80a5e3e commit 46efed4
Show file tree
Hide file tree
Showing 5 changed files with 444 additions and 511 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- `Provable.runAndCheckSync()` added and immediately deprecated for a smoother upgrade path for tests
- `Reducer.reduce()` requires the maximum number of actions per method as an explicit (optional) argument https://github.com/o1-labs/o1js/pull/1450
- The default value is 1 and should work for most existing contracts
- `new UInt64()` and `UInt64.from()` no longer unsafely accept a field element as input. https://github.com/o1-labs/o1js/pull/1438 [@julio4](https://github.com/julio4)
As a replacement, `UInt64.Unsafe.fromField()` was introduced
- This prevents you from accidentally creating a `UInt64` without proving that it fits in 64 bits
- Equivalent changes were made to `UInt32`

### Added

Expand Down
11 changes: 6 additions & 5 deletions src/lib/circuit-value.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,16 @@ await Provable.runAndCheck(() => {
});

// should fail `check` if `check` of subfields doesn't pass

// manually construct an invalid uint32
let noUint32 = new UInt32(1);
noUint32.value = Field(-1);

await expect(() =>
Provable.runAndCheck(() => {
let x = Provable.witness(type, () => ({
...value,
uint: [
UInt32.zero,
// invalid Uint32
new UInt32(Field(-1)),
],
uint: [UInt32.zero, noUint32],
}));
})
).rejects.toThrow(`Constraint unsatisfied`);
Expand Down
14 changes: 7 additions & 7 deletions src/lib/gadgets/sha256.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function padding(data: FlexibleBytes): UInt32[][] {
// chunk 4 bytes into one UInt32, as expected by SHA256
// bytesToWord expects little endian, so we reverse the bytes
chunks.push(
UInt32.from(bytesToWord(paddedMessage.slice(i, i + 4).reverse()))
UInt32.Unsafe.fromField(bytesToWord(paddedMessage.slice(i, i + 4).reverse()))
);
}

Expand Down Expand Up @@ -104,7 +104,7 @@ const SHA256 = {
.add(DeltaZero(W[t - 15]).value.add(W[t - 16].value));

// mod 32bit the unreduced field element
W[t] = UInt32.from(divMod32(unreduced, 16).remainder);
W[t] = UInt32.Unsafe.fromField(divMod32(unreduced, 16).remainder);
}

// initialize working variables
Expand Down Expand Up @@ -133,11 +133,11 @@ const SHA256 = {
h = g;
g = f;
f = e;
e = UInt32.from(divMod32(d.value.add(unreducedT1), 16).remainder); // mod 32bit the unreduced field element
e = UInt32.Unsafe.fromField(divMod32(d.value.add(unreducedT1), 16).remainder); // mod 32bit the unreduced field element
d = c;
c = b;
b = a;
a = UInt32.from(divMod32(unreducedT2.add(unreducedT1), 16).remainder); // mod 32bit
a = UInt32.Unsafe.fromField(divMod32(unreducedT2.add(unreducedT1), 16).remainder); // mod 32bit
}

// new intermediate hash value
Expand All @@ -163,7 +163,7 @@ function Ch(x: UInt32, y: UInt32, z: UInt32) {
let xAndY = x.and(y).value;
let xNotAndZ = x.not().and(z).value;
let ch = xAndY.add(xNotAndZ).seal();
return UInt32.from(ch);
return UInt32.Unsafe.fromField(ch);
}

function Maj(x: UInt32, y: UInt32, z: UInt32) {
Expand All @@ -172,7 +172,7 @@ function Maj(x: UInt32, y: UInt32, z: UInt32) {
let sum = x.value.add(y.value).add(z.value).seal();
let xor = x.xor(y).xor(z).value;
let maj = sum.sub(xor).div(2).seal();
return UInt32.from(maj);
return UInt32.Unsafe.fromField(maj);
}

function SigmaZero(x: UInt32) {
Expand Down Expand Up @@ -276,5 +276,5 @@ function sigma(u: UInt32, bits: TupleN<number, 3>, firstShifted = false) {

// since xor() is implicitly range-checking both of its inputs, this provides the missing
// proof that xRotR0, xRotR1, xRotR2 < 2^32, which implies x0 < 2^d0, x1 < 2^d1, x2 < 2^d2
return UInt32.from(xRotR0).xor(new UInt32(xRotR1)).xor(new UInt32(xRotR2));
return UInt32.Unsafe.fromField(xRotR0).xor(UInt32.Unsafe.fromField(xRotR1)).xor(UInt32.Unsafe.fromField(xRotR2));
}
Loading

0 comments on commit 46efed4

Please sign in to comment.