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

actionState precondition causes Invalid signature on fee payer error #1966

Open
dfstio opened this issue Jan 7, 2025 · 3 comments
Open

actionState precondition causes Invalid signature on fee payer error #1966

dfstio opened this issue Jan 7, 2025 · 3 comments

Comments

@dfstio
Copy link

dfstio commented Jan 7, 2025

Adding the line

const update = AccountUpdate.create(address);
update.body.preconditions.account.actionState = {
      isSome: Bool(false),
      value: Field(0),
    };

causes the following error:

 Transaction failed with errors:
    - Check signature: Invalid signature on fee payer for key B62qmvmaybzt8hFaZtRzWhnsNFMysGsEygLNsgfz7C38QYenHa1Zda5

All other preconditions work as expected; this error occurs only when the actionState precondition is used.

The example to reproduce it:

import { describe, expect, it } from "@jest/globals";

import {
  SmartContract,
  method,
  AccountUpdate,
  state,
  State,
  Mina,
  Field,
  PublicKey,
  Bool,
  fetchAccount,
} from "o1js";

const { TestPublicKey } = Mina;
type TestPublicKey = Mina.TestPublicKey;
const zkKey1 = TestPublicKey.random();
const zkKey2 = TestPublicKey.random();

let sender: TestPublicKey;

class MyContract1 extends SmartContract {
  @state(Field) value = State<Field>(Field(1));

  @method
  public async setValue(value: Field) {
    this.value.set(value);
  }
}

class MyContract2 extends SmartContract {
  @state(Field) value = State<Field>(Field(1));

  @method
  public async setValue(value: Field, address: PublicKey) {
    const update = AccountUpdate.create(address);
    update.body.preconditions.account.actionState = {
      isSome: Bool(false),
      value: Field(0),
    };
    this.value.set(value);
  }
}

const contract1 = new MyContract1(zkKey1);
const contract2 = new MyContract2(zkKey2);

describe("actionState error", () => {
  it(`should compile`, async () => {
    const Local = await Mina.LocalBlockchain();
    Mina.setActiveInstance(Local);
    sender = Local.testAccounts[0];
    await MyContract1.compile();
    await MyContract2.compile();
  });
  it(`should deploy`, async () => {
    await fetchAccount({ publicKey: sender });
    const tx = await Mina.transaction(
      { sender, fee: 100_000_000, memo: "deploy" },
      async () => {
        AccountUpdate.fundNewAccount(sender, 2);
        await contract1.deploy({});
        await contract2.deploy({});
      }
    );
    await tx.sign([sender.key, zkKey1.key, zkKey2.key]).send();
  });

  it(`should update`, async () => {
    await fetchAccount({ publicKey: sender });
    await fetchAccount({ publicKey: zkKey1 });
    await fetchAccount({ publicKey: zkKey2 });

    const tx = await Mina.transaction(
      { sender, fee: 100_000_000, memo: `update` },
      async () => {
        await contract2.setValue(Field(1), zkKey1);
      }
    );
    await tx.prove();
    await tx.sign([sender.key]).send();
  });
});

@mitschabaude
Copy link
Collaborator

I think this is because you're setting the precondition to a non-standard falsy value which is encoded as 'null' in the JSON and decoded into the default falsy value in the OCaml code that checks the signature. Thus, the signature doesn't verify because something else was signed.

@mitschabaude
Copy link
Collaborator

I think the built-in methods for setting and unsetting preconditions should handle this correctly

@dfstio
Copy link
Author

dfstio commented Jan 7, 2025

Setting actionState.isSome to true and the actionsState.value to the actual value does resolve this problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants