-
Notifications
You must be signed in to change notification settings - Fork 110
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
Decouple the compile-time and runtime artifacts of offchain state #1832
Comments
Proposed APII think a more ergonomic API would use the class MyOffchainState extends OffchainState(
{
someMap: OffchainState.Map(PublicKey, UInt64),
someValue: OffchainState.Field(UInt64),
},
{ logTotalCapacity: 10, maxActionsPerProof: 5 }
) {}
class MySmartContract extends SmartContract {
@state(MyOffchainState.Commitments) offchainState = MyOffchainState.initialCommitments();
@method
async settle(proof: MyOffchainState.Proof) {
proof.verify();
const commitments = this.offchainState.getAndRequireEquals();
proof.publicInputs.commitments.assertEqual(commitments);
this.offchainState.set(proof.publicOutput.commitments);
}
} By using a class in the compilation of the offchain state zk program and the smart contract, the developer could have many instances of |
I agree on the direction! But in your proposed API, where/how is |
It is only the commitment that are referenced in the smart contract. Then the |
Ah I see, I missed that! But then, what about the API for getting and setting offchain state fields? |
Somehow, for doing offchain state operations, the smart contract needs access to the Merkle map that the offchain state is kept in. Currently, there is just a single Merkle map per offchain state "class", but I think we want to avoid that - because the Merkle map is created from actions fetched from a particular account, so there should never be two different accounts used with the same Merkle map. A contract instance is basically a representation of zkapp account, so it makes sense to require a 1:1 correspondence between contract instances and offchain Merkle maps. |
How about this @45930? // not a class, because users don't need any features of classes like adding methods
const offchainState = OffchainState(
{
someMap: OffchainState.Map(PublicKey, UInt64),
someValue: OffchainState.Field(UInt64),
},
{ logTotalCapacity: 10, maxActionsPerProof: 5 }
);
class StateProof extends offchainState.Proof {}
class MySmartContract extends SmartContract {
@state(MyOffchainState.Commitments) offchainCommitments = MyOffchainState.initialCommitments();
// instantiate for this contract
// replaces previous `setContractClass()` / `setContractInstance()`
offchainState = offchainState(MySmartContract);
@method.returns(UInt64)
async getBalance(address: PublicKey) {
return (await this.offchainState.fields.accounts.get(address)).orElse(0n);
}
@method
async settle(proof: StateProof) {
await this.offchainState.settle(proof);
}
} |
Ah right right right... So a non-provable property like
But do we even need that? If we point to an existing deployed smart contract that we haven't caught up with yet, then we can sync the actions: o1js/src/lib/mina/actions/offchain-state.ts Line 219 in 3ef4f6f
So we don't necessarily need to track a local version. We could instead emit actions that are especially defined by the |
I think it's important to keep the design capable of basic efficiency, i.e. not fetch all actions every time we want access to a state field. So I do think we want a local store. |
This is fair enough, but also breaks down if more than one party operates the contract right? We can't guarantee that all actions will be routed through our operator, and not someone else's. In any case, I think we can keep the local storage, but make it a little easier to reset or edit the |
Yeah and there should be a method to re-sync the local store to any new actions from the network |
Yeah that's clean! |
Summary
The way that offchain state works today is a developer will create their custom offchain state class and object in on call:
This object is then passed into the definition of the smart contract, e.g. in the
settle
method:Because the specific object called
offchainState
is referenced in the smart contract, the object and the class become linked. Every instance of the smart contract class will reference the same objectoffchainState
.Where has this caused issues?
There is a community builder working on a project that has run into this issue: https://discord.com/channels/484437221055922177/1287933364007079967
They have duplicates of the same smart contract with which they want to use offchain state.
I also ran into this problem when trying to write isolated unit tests for an app that uses offchain state.
The text was updated successfully, but these errors were encountered: