Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smart Contract accepts any proof as long as types match #1231

Closed
emlautarom1 opened this issue Nov 6, 2023 · 0 comments · Fixed by #1302
Closed

Smart Contract accepts any proof as long as types match #1231

emlautarom1 opened this issue Nov 6, 2023 · 0 comments · Fixed by #1302
Assignees
Labels
bug Something isn't working

Comments

@emlautarom1
Copy link

According to the docs, we can use proofs created in the browser as parameters for a method in a Smart Contract which will get verified by the contract as follows:

@method foo(proof: Proof) {
  proof.verify().assertTrue();
  /* ... the rest of our method
   * For example using the total value as the fee for some other transaction. */
}

First of all, the previous code does not compile due to:

  • Proof being a generic type (Proof<I, O>)
  • Not being able to use Proof directly (we need to subclass it).
  • assertTrue() is not available due to verify() returning void.

I followed the code in the examples repository (https://github.com/o1-labs/docs2/blob/main/examples/zkapps/09-recursion/src/rollup.ts) and I ended up with the following example:

import { AccountUpdate, Bool, Experimental, Mina, PrivateKey, PublicKey, SmartContract, State, UInt64, method, state } from 'o1js';

export const RealProof = Experimental.ZkProgram({
  methods: {
    make: {
      privateInputs: [UInt64],

      method(value: UInt64) {
        let expected = UInt64.from(34);
        value.assertEquals(expected);
      },
    },
  },
});

export const FakeProof = Experimental.ZkProgram({
  methods: {
    make: {
      privateInputs: [UInt64],

      method(value: UInt64) {
        Bool(true).assertTrue();
      },
    },
  },
});

class BrokenProof extends Experimental.ZkProgram.Proof(RealProof) { }
class Broken extends SmartContract {
  @state(Bool) isValid = State<Bool>();

  init() {
    super.init();
    this.isValid.set(Bool(false));
  }

  @method setValid(proof: BrokenProof) {
    proof.verify();
    this.isValid.set(Bool(true));
  }
}

describe('Broken', () => {
  let deployerAccount: PublicKey;
  let deployerKey: PrivateKey;
  let senderAccount: PublicKey;
  let senderKey: PrivateKey;
  let zkAppAddress: PublicKey;
  let zkAppPrivateKey: PrivateKey;
  let zkApp: Broken;

  beforeAll(async () => {
    await RealProof.compile();
    await FakeProof.compile();
    await Broken.compile();
  });

  beforeEach(() => {
    const Local = Mina.LocalBlockchain({ proofsEnabled: true });
    Mina.setActiveInstance(Local);
    ({ privateKey: deployerKey, publicKey: deployerAccount } = Local.testAccounts[0]);
    ({ privateKey: senderKey, publicKey: senderAccount } = Local.testAccounts[1]);
    zkAppPrivateKey = PrivateKey.random();
    zkAppAddress = zkAppPrivateKey.toPublicKey();
    zkApp = new Broken(zkAppAddress);
  });

  async function localDeploy() {
    const txn = await Mina.transaction(deployerAccount, () => {
      AccountUpdate.fundNewAccount(deployerAccount);
      zkApp.deploy();
    });
    await txn.prove();
    await txn.sign([deployerKey, zkAppPrivateKey]).send();
  }

  it('accepts a fake proof', async () => {
    await localDeploy();

    const value = UInt64.from(99999);
    const fakeProof = await FakeProof.make(value);

    const txn = await Mina.transaction(senderAccount, () => {
      zkApp.setValid(fakeProof);
    });
    await txn.prove();
    await txn.sign([senderKey]).send();

    const isValid = zkApp.isValid.get();
    expect(isValid).toEqual(Bool(true));
  });
});

Note how we're able to use FakeProof despite expecting a RealProof. Either the code above is incorrect (should be written differently), or this is a bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants