#Should a verification key change, if a constant inside the circuit changes?

2 messages · Page 1 of 1 (latest)

sullen lion
#

I have a simple contract/circuit, and i'd like to know when is the resulting verification key meant to change? Because from my observation, changing the 'const field' to a different value, does not change the verification key. Is this meant to be? Note: there are actually two constants, both Fields in these examples.

class TestContract extends SmartContract {
  @method
  assert() {
    const field = Field(0);
    field.assertEquals(Field(0));
  }
}

// const field = Field(0) and .assertEquals(Field(0))
verification key: 7948290093200245896508944589480762942981031779572753481662585512495325656000

// const field = Field(1) and .assertEquals(Field(1))
verification key: 7948290093200245896508944589480762942981031779572753481662585512495325656000

^^ same verification key in both const cases

^^ both verification keys are the same, even tho the 'circuit constant' (const field) has changed, is this intentional? In my understanding the const should be a part of the circuit therefore i'd expect it to change the verification key when changed

The verification key is changed together with the constant, if .assertLte is used instead of .assertEquals:

// const = Field(0) and .assertLte(Field(0))
verification key: 25042330595415981771119229777367115064043240572771754696131063485884945220088

// const = Field(0) and .assertLte(Field(1))
verification key: 5450372029939486778107747299903230310201247331835086151068760972857259830379

^^ different verification key

Summoning pioneers of snarky @full flare @viscid nymph @swift horizon 👀

full flare
#

Hey @sullen lion, the reason that the vk doesn't change here is because your assertion is a no-op and never makes it into the circuit.

It's important to understand that there are two, fundamentally different kinds of values in a circuit: constants and variables.

Constants are created when you create Field etc directly from JS values, like numbers or strings:

let x = Field(0); // x is a constant
let b = Bool(false); // b is a constant

Variables are created either

  • by using Circuit.witness()
  • by passing values to a @method (which uses Circuit.witness under the hood)
@method myMethod(x: Field) { 
  // x is a variable
  let b = Circuit.witness(Bool, () => Bool(true)); // b is a variable
}

A circuit is formed by creating constraints on variables. That's what a circuit fundamentally is: A list of constraints on variables.
If something never affects any constraint on any variable, then it won't become part of the circuit. (It can't, since by definition the circuit is a list of constraints on variables.)

The code in your example does assertEquals between two constants:

const field = Field(0); // field is a constant
field.assertEquals(Field(0)); // assertEqals with another constant

So, this doesn't create a constraint on any variable. Therefore, it doesn't affect the circuit. Therefore, changing parts of it doesn't affect the verification key,

This would be similar code where you create a constraint between a variable and a constant. Here, changing the constant does affect the VK:

  @method assert(field: Field) {
    field.assertEquals(Field(0));
  }