@proto-kit/protocol 0.1.1-develop.190 → 0.1.1-develop.211
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/blockmodules/AccountStateModule.d.ts +38 -0
- package/dist/blockmodules/AccountStateModule.d.ts.map +1 -0
- package/dist/blockmodules/AccountStateModule.js +38 -0
- package/dist/blockmodules/NoopTransactionHook.d.ts +6 -0
- package/dist/blockmodules/NoopTransactionHook.d.ts.map +1 -0
- package/dist/blockmodules/NoopTransactionHook.js +5 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/model/Option.d.ts +8 -8
- package/dist/model/Option.d.ts.map +1 -1
- package/dist/model/Option.js +7 -15
- package/dist/model/StateTransition.d.ts.map +1 -1
- package/dist/model/StateTransitionProvableBatch.d.ts +59 -1
- package/dist/model/StateTransitionProvableBatch.d.ts.map +1 -1
- package/dist/model/StateTransitionProvableBatch.js +58 -4
- package/dist/protocol/Protocol.d.ts +21 -6
- package/dist/protocol/Protocol.d.ts.map +1 -1
- package/dist/protocol/Protocol.js +44 -1
- package/dist/protocol/ProtocolModule.d.ts +2 -3
- package/dist/protocol/ProtocolModule.d.ts.map +1 -1
- package/dist/protocol/ProtocolModule.js +1 -3
- package/dist/protocol/ProvableTransactionHook.d.ts +6 -0
- package/dist/protocol/ProvableTransactionHook.d.ts.map +1 -0
- package/dist/protocol/ProvableTransactionHook.js +3 -0
- package/dist/protocol/TransitioningProtocolModule.d.ts +5 -0
- package/dist/protocol/TransitioningProtocolModule.d.ts.map +1 -0
- package/dist/protocol/TransitioningProtocolModule.js +3 -0
- package/dist/prover/block/BlockProvable.d.ts +2 -2
- package/dist/prover/block/BlockProvable.d.ts.map +1 -1
- package/dist/prover/block/BlockProver.d.ts +25 -11
- package/dist/prover/block/BlockProver.d.ts.map +1 -1
- package/dist/prover/block/BlockProver.js +74 -17
- package/dist/prover/statetransition/StateTransitionProvable.d.ts +18 -2
- package/dist/prover/statetransition/StateTransitionProvable.d.ts.map +1 -1
- package/dist/prover/statetransition/StateTransitionProvable.js +2 -0
- package/dist/prover/statetransition/StateTransitionProver.d.ts +16 -6
- package/dist/prover/statetransition/StateTransitionProver.d.ts.map +1 -1
- package/dist/prover/statetransition/StateTransitionProver.js +45 -13
- package/dist/state/State.d.ts +60 -0
- package/dist/state/State.d.ts.map +1 -0
- package/dist/state/State.js +116 -0
- package/dist/state/StateMap.d.ts +37 -0
- package/dist/state/StateMap.d.ts.map +1 -0
- package/dist/state/StateMap.js +56 -0
- package/dist/state/StateService.d.ts +6 -0
- package/dist/state/StateService.d.ts.map +1 -0
- package/dist/state/StateService.js +1 -0
- package/dist/state/StateServiceProvider.d.ts +10 -0
- package/dist/state/StateServiceProvider.d.ts.map +1 -0
- package/dist/state/StateServiceProvider.js +42 -0
- package/dist/state/assert/assert.d.ts +12 -0
- package/dist/state/assert/assert.d.ts.map +1 -0
- package/dist/state/assert/assert.js +23 -0
- package/dist/state/context/ProtocolMethodExecutionContext.d.ts +22 -0
- package/dist/state/context/ProtocolMethodExecutionContext.d.ts.map +1 -0
- package/dist/state/context/ProtocolMethodExecutionContext.js +28 -0
- package/dist/state/context/RuntimeMethodExecutionContext.d.ts +60 -0
- package/dist/state/context/RuntimeMethodExecutionContext.d.ts.map +1 -0
- package/dist/state/context/RuntimeMethodExecutionContext.js +105 -0
- package/dist/state/context/TransitionMethodExecutionContext.d.ts +23 -0
- package/dist/state/context/TransitionMethodExecutionContext.d.ts.map +1 -0
- package/dist/state/context/TransitionMethodExecutionContext.js +6 -0
- package/dist/state/protocol/ProtocolState.d.ts +7 -0
- package/dist/state/protocol/ProtocolState.d.ts.map +1 -0
- package/dist/state/protocol/ProtocolState.js +42 -0
- package/dist/utils/merkletree/MemoryMerkleTreeStorage.d.ts +26 -0
- package/dist/utils/merkletree/MemoryMerkleTreeStorage.d.ts.map +1 -0
- package/dist/utils/merkletree/MemoryMerkleTreeStorage.js +79 -0
- package/package.json +5 -3
- package/src/blockmodules/AccountStateModule.ts +31 -0
- package/src/blockmodules/NoopTransactionHook.ts +7 -0
- package/src/index.ts +12 -0
- package/src/model/Option.ts +18 -22
- package/src/model/StateTransition.ts +1 -1
- package/src/model/StateTransitionProvableBatch.ts +86 -5
- package/src/protocol/Protocol.ts +85 -23
- package/src/protocol/ProtocolModule.ts +1 -7
- package/src/protocol/ProvableTransactionHook.ts +7 -0
- package/src/protocol/TransitioningProtocolModule.ts +5 -0
- package/src/prover/block/BlockProvable.ts +2 -2
- package/src/prover/block/BlockProver.ts +139 -21
- package/src/prover/statetransition/StateTransitionProvable.ts +4 -2
- package/src/prover/statetransition/StateTransitionProver.ts +93 -13
- package/src/state/State.ts +160 -0
- package/src/state/StateMap.ts +74 -0
- package/src/state/StateService.ts +6 -0
- package/src/state/StateServiceProvider.ts +37 -0
- package/src/state/assert/assert.test.ts +49 -0
- package/src/state/assert/assert.ts +28 -0
- package/src/state/context/ProtocolMethodExecutionContext.ts +36 -0
- package/src/state/context/RuntimeMethodExecutionContext.ts +124 -0
- package/src/state/context/TransitionMethodExecutionContext.ts +27 -0
- package/src/state/protocol/ProtocolState.ts +63 -0
- package/test/BlockProver.test.ts +139 -36
- package/test/Protocol.test.ts +22 -5
- package/test/StateTransition.test.ts +1 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { inject, injectable } from "tsyringe";
|
|
2
|
+
|
|
3
|
+
import { StateService } from "./StateService";
|
|
4
|
+
|
|
5
|
+
const errors = {
|
|
6
|
+
stateServiceNotSet: () =>
|
|
7
|
+
new Error(
|
|
8
|
+
`StateService has not been set yet. Be sure to either call your runtime or
|
|
9
|
+
protocol function by creating them with an AppChain or by setting the
|
|
10
|
+
stateService manually.`
|
|
11
|
+
),
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
@injectable()
|
|
15
|
+
export class StateServiceProvider {
|
|
16
|
+
private readonly defaultStateService?: StateService =
|
|
17
|
+
this.currentStateService;
|
|
18
|
+
|
|
19
|
+
public constructor(
|
|
20
|
+
@inject("StateService") private currentStateService?: StateService
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
public get stateService(): StateService {
|
|
24
|
+
if (this.currentStateService === undefined) {
|
|
25
|
+
throw errors.stateServiceNotSet();
|
|
26
|
+
}
|
|
27
|
+
return this.currentStateService;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public setCurrentStateService(service: StateService) {
|
|
31
|
+
this.currentStateService = service;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public resetToDefault() {
|
|
35
|
+
this.currentStateService = this.defaultStateService;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
|
|
3
|
+
import { Bool } from "snarkyjs";
|
|
4
|
+
import { container } from "tsyringe";
|
|
5
|
+
|
|
6
|
+
import { assert } from "./assert";
|
|
7
|
+
import { RuntimeMethodExecutionContext } from "../context/RuntimeMethodExecutionContext";
|
|
8
|
+
|
|
9
|
+
describe("assert", () => {
|
|
10
|
+
const defaultStatusMessage = "something went wrong";
|
|
11
|
+
const executionContext = container.resolve(RuntimeMethodExecutionContext);
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
executionContext.beforeMethod("testConstructor", "test", []);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
executionContext.afterMethod();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe.each([
|
|
22
|
+
[true, undefined],
|
|
23
|
+
[false, undefined],
|
|
24
|
+
[false, defaultStatusMessage],
|
|
25
|
+
])("status and message propagation", (status, statusMessage) => {
|
|
26
|
+
it("should propagate the assertion status and message", () => {
|
|
27
|
+
expect.assertions(2);
|
|
28
|
+
|
|
29
|
+
assert(Bool(status), statusMessage);
|
|
30
|
+
|
|
31
|
+
const { status: resultStatus, statusMessage: resultStatusMessage } =
|
|
32
|
+
executionContext.current().result;
|
|
33
|
+
|
|
34
|
+
expect(status).toBe(resultStatus.toBoolean());
|
|
35
|
+
expect(statusMessage).toBe(resultStatusMessage);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("should keep a false status, once it was already set", () => {
|
|
40
|
+
expect.assertions(1);
|
|
41
|
+
|
|
42
|
+
assert(Bool(false));
|
|
43
|
+
assert(Bool(true));
|
|
44
|
+
|
|
45
|
+
const { status } = executionContext.current().result;
|
|
46
|
+
|
|
47
|
+
expect(status.toBoolean()).toBe(false);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Bool, Provable } from "snarkyjs";
|
|
2
|
+
import { container } from "tsyringe";
|
|
3
|
+
import { log } from "@proto-kit/common";
|
|
4
|
+
|
|
5
|
+
import { RuntimeMethodExecutionContext } from "../context/RuntimeMethodExecutionContext";
|
|
6
|
+
import { exec } from "child_process";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Maintains an execution status of the current runtime module method,
|
|
10
|
+
* while prioritizing one-time failures. The assertion won't change the
|
|
11
|
+
* execution status if it has previously failed at least once within the
|
|
12
|
+
* same method execution context.
|
|
13
|
+
*
|
|
14
|
+
* @param condition - Result of the assertion made about the execution status
|
|
15
|
+
* @param message - Optional message describing the prior status
|
|
16
|
+
*/
|
|
17
|
+
export function assert(condition: Bool, message?: string) {
|
|
18
|
+
const executionContext = container.resolve(RuntimeMethodExecutionContext);
|
|
19
|
+
const previousStatus = executionContext.current().result.status;
|
|
20
|
+
const status = Provable.if(previousStatus, Bool, condition, previousStatus);
|
|
21
|
+
|
|
22
|
+
if (!condition.toBoolean()) {
|
|
23
|
+
log.debug("Assertion failed: ", message);
|
|
24
|
+
executionContext.setStatusMessage(message);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
executionContext.setStatus(status);
|
|
28
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TransitionMethodExecutionContext,
|
|
3
|
+
TransitionMethodExecutionResult
|
|
4
|
+
} from "./TransitionMethodExecutionContext";
|
|
5
|
+
import { StateTransition } from "../../model/StateTransition";
|
|
6
|
+
|
|
7
|
+
export class ProtocolMethodExecutionContext implements TransitionMethodExecutionContext {
|
|
8
|
+
public result = new TransitionMethodExecutionResult();
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Adds an in-method generated state transition to the current context
|
|
12
|
+
* @param stateTransition - State transition to add to the context
|
|
13
|
+
*/
|
|
14
|
+
public addStateTransition<Value>(
|
|
15
|
+
stateTransition: StateTransition<Value>
|
|
16
|
+
) {
|
|
17
|
+
this.result.stateTransitions.push(stateTransition);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Manually clears/resets the execution context
|
|
22
|
+
*/
|
|
23
|
+
public clear() {
|
|
24
|
+
this.result = new TransitionMethodExecutionResult();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Had to override current() otherwise it would not infer
|
|
29
|
+
* the type of result correctly (parent type would be reused)
|
|
30
|
+
*/
|
|
31
|
+
public current() {
|
|
32
|
+
return {
|
|
33
|
+
result: this.result,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Bool } from "snarkyjs";
|
|
2
|
+
import { singleton } from "tsyringe";
|
|
3
|
+
import { ProvableMethodExecutionContext, ProvableMethodExecutionResult } from "@proto-kit/common";
|
|
4
|
+
import { StateTransition } from "../../model/StateTransition";
|
|
5
|
+
import { RuntimeTransaction } from "../../model/transaction/RuntimeTransaction";
|
|
6
|
+
import { NetworkState } from "../../model/network/NetworkState";
|
|
7
|
+
|
|
8
|
+
const errors = {
|
|
9
|
+
setupNotCalled: () =>
|
|
10
|
+
new Error(
|
|
11
|
+
"Setup has not been called prior to executing a runtime method. Be sure to do that so that the Runtime is setup property for execution"
|
|
12
|
+
),
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export class RuntimeProvableMethodExecutionResult extends ProvableMethodExecutionResult {
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
public stateTransitions: StateTransition<any>[] = [];
|
|
18
|
+
|
|
19
|
+
public status: Bool = Bool(true);
|
|
20
|
+
|
|
21
|
+
public statusMessage?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface RuntimeMethodExecutionData {
|
|
25
|
+
transaction: RuntimeTransaction;
|
|
26
|
+
networkState: NetworkState;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Execution context used to wrap runtime module methods,
|
|
31
|
+
* allowing them to post relevant information (such as execution status)
|
|
32
|
+
* into the context without any unnecessary 'prop drilling'.
|
|
33
|
+
*/
|
|
34
|
+
@singleton()
|
|
35
|
+
export class RuntimeMethodExecutionContext extends ProvableMethodExecutionContext {
|
|
36
|
+
public methods: string[] = [];
|
|
37
|
+
|
|
38
|
+
public input: RuntimeMethodExecutionData | undefined;
|
|
39
|
+
|
|
40
|
+
// The input corresponding to the current result
|
|
41
|
+
private lastInput: RuntimeMethodExecutionData | undefined;
|
|
42
|
+
|
|
43
|
+
public override result = new RuntimeProvableMethodExecutionResult();
|
|
44
|
+
|
|
45
|
+
private isSimulated: boolean = false;
|
|
46
|
+
|
|
47
|
+
private assertSetupCalled(): asserts this is {
|
|
48
|
+
input: RuntimeMethodExecutionData;
|
|
49
|
+
} {
|
|
50
|
+
if (this.input === undefined) {
|
|
51
|
+
throw errors.setupNotCalled();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Adds an in-method generated state transition to the current context
|
|
57
|
+
* @param stateTransition - State transition to add to the context
|
|
58
|
+
*/
|
|
59
|
+
public addStateTransition<Value>(stateTransition: StateTransition<Value>) {
|
|
60
|
+
this.assertSetupCalled();
|
|
61
|
+
this.result.stateTransitions.push(stateTransition);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param message - Status message to acompany the current status
|
|
66
|
+
*/
|
|
67
|
+
public setStatusMessage(message?: string) {
|
|
68
|
+
this.assertSetupCalled();
|
|
69
|
+
if (this.isSimulated) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
this.result.statusMessage ??= message;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @param status - Execution status of the current method
|
|
77
|
+
*/
|
|
78
|
+
public setStatus(status: Bool) {
|
|
79
|
+
this.assertSetupCalled();
|
|
80
|
+
if (this.isSimulated) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
this.result.status = status;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @param input Input witness data required for a runtime execution
|
|
88
|
+
*/
|
|
89
|
+
public setup(input: RuntimeMethodExecutionData) {
|
|
90
|
+
this.input = input;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public setSimulated(simulated: boolean) {
|
|
94
|
+
this.isSimulated = simulated;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Manually clears/resets the execution context
|
|
99
|
+
*/
|
|
100
|
+
public clear() {
|
|
101
|
+
this.result = new RuntimeProvableMethodExecutionResult();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public afterMethod() {
|
|
105
|
+
super.afterMethod();
|
|
106
|
+
if (this.isFinished) {
|
|
107
|
+
this.lastInput = this.input;
|
|
108
|
+
this.input = undefined;
|
|
109
|
+
this.isSimulated = false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Had to override current() otherwise it would not infer
|
|
115
|
+
* the type of result correctly (parent type would be reused)
|
|
116
|
+
*/
|
|
117
|
+
public current() {
|
|
118
|
+
return {
|
|
119
|
+
isFinished: this.isFinished,
|
|
120
|
+
result: this.result,
|
|
121
|
+
input: this.lastInput,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { StateTransition } from "../../model/StateTransition";
|
|
2
|
+
|
|
3
|
+
export class TransitionMethodExecutionResult {
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
|
+
public stateTransitions: StateTransition<any>[] = [];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface TransitionMethodExecutionContext {
|
|
9
|
+
/**
|
|
10
|
+
* Adds an in-method generated state transition to the current context
|
|
11
|
+
* @param stateTransition - State transition to add to the context
|
|
12
|
+
*/
|
|
13
|
+
addStateTransition: <Value>(stateTransition: StateTransition<Value>) => void;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Manually clears/resets the execution context
|
|
17
|
+
*/
|
|
18
|
+
clear: () => void;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Had to override current() otherwise it would not infer
|
|
22
|
+
* the type of result correctly (parent type would be reused)
|
|
23
|
+
*/
|
|
24
|
+
current: () => {
|
|
25
|
+
result: TransitionMethodExecutionResult;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { State } from "../State";
|
|
2
|
+
import { ToFieldable } from "../../model/Option";
|
|
3
|
+
import { Path } from "../../model/Path";
|
|
4
|
+
import { TransitioningProtocolModule } from "../../protocol/TransitioningProtocolModule";
|
|
5
|
+
|
|
6
|
+
const errors = {
|
|
7
|
+
missingName: (className: string) =>
|
|
8
|
+
new Error(
|
|
9
|
+
`Unable to provide a unique identifier for state, ${className} is missing a name.
|
|
10
|
+
Did you forget to extend your block module with 'extends ...Hook'?`
|
|
11
|
+
),
|
|
12
|
+
|
|
13
|
+
missingProtocol: (className: string) =>
|
|
14
|
+
new Error(
|
|
15
|
+
`Unable to provide 'procotol' for state, ${className} is missing a name.
|
|
16
|
+
Did you forget to extend your block module with 'extends ...Hook'?`
|
|
17
|
+
),
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Decorates a runtime module property as state, passing down some
|
|
22
|
+
* underlying values to improve developer experience.
|
|
23
|
+
*/
|
|
24
|
+
export function protocolState() {
|
|
25
|
+
return <TargetTransitioningModule extends TransitioningProtocolModule>(
|
|
26
|
+
target: TargetTransitioningModule,
|
|
27
|
+
propertyKey: string
|
|
28
|
+
) => {
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/init-declarations
|
|
30
|
+
let value: State<unknown> | undefined;
|
|
31
|
+
|
|
32
|
+
Object.defineProperty(target, propertyKey, {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
|
|
35
|
+
get: function get() {
|
|
36
|
+
// eslint-disable-next-line max-len
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38
|
+
const self = this as TargetTransitioningModule;
|
|
39
|
+
|
|
40
|
+
if (self.name === undefined) {
|
|
41
|
+
throw errors.missingName(self.constructor.name);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!self.protocol) {
|
|
45
|
+
throw errors.missingProtocol(self.constructor.name);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// eslint-disable-next-line no-warning-comments
|
|
49
|
+
// TODO Add Prefix?
|
|
50
|
+
const path = Path.fromProperty(self.name, propertyKey);
|
|
51
|
+
if (value) {
|
|
52
|
+
value.path = path;
|
|
53
|
+
value.stateServiceProvider = self.protocol.stateServiceProvider;
|
|
54
|
+
}
|
|
55
|
+
return value;
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
set: (newValue: State<unknown>) => {
|
|
59
|
+
value = newValue;
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
}
|
package/test/BlockProver.test.ts
CHANGED
|
@@ -1,45 +1,114 @@
|
|
|
1
1
|
import "reflect-metadata";
|
|
2
|
-
import { Bool, Field, Poseidon, Proof } from "snarkyjs";
|
|
3
2
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
Bool,
|
|
4
|
+
Experimental,
|
|
5
|
+
Field,
|
|
6
|
+
PrivateKey,
|
|
7
|
+
Proof,
|
|
8
|
+
UInt64,
|
|
9
|
+
} from "snarkyjs";
|
|
9
10
|
|
|
10
11
|
import {
|
|
11
12
|
BlockProver,
|
|
12
13
|
type BlockProverState,
|
|
13
|
-
} from "../src/prover/block/BlockProver
|
|
14
|
-
import { NoOpStateTransitionWitnessProvider } from "../src/prover/statetransition/StateTransitionWitnessProvider
|
|
14
|
+
} from "../src/prover/block/BlockProver";
|
|
15
|
+
import { NoOpStateTransitionWitnessProvider } from "../src/prover/statetransition/StateTransitionWitnessProvider";
|
|
15
16
|
import {
|
|
16
17
|
StateTransitionProverPublicInput,
|
|
17
18
|
StateTransitionProverPublicOutput,
|
|
18
19
|
} from "../src/prover/statetransition/StateTransitionProvable";
|
|
19
20
|
import { BlockProverPublicInput } from "../src/prover/block/BlockProvable";
|
|
21
|
+
import {
|
|
22
|
+
AreProofsEnabled,
|
|
23
|
+
PlainZkProgram,
|
|
24
|
+
WithZkProgrammable,
|
|
25
|
+
ZkProgrammable,
|
|
26
|
+
} from "@proto-kit/common";
|
|
27
|
+
import ZkProgram = Experimental.ZkProgram;
|
|
28
|
+
import { UnsignedTransaction } from "@proto-kit/sequencer";
|
|
29
|
+
import { AccountStateModule } from "../src/blockmodules/AccountStateModule";
|
|
30
|
+
import { container } from "tsyringe";
|
|
31
|
+
import {
|
|
32
|
+
BlockModule, DefaultProvableHashList,
|
|
33
|
+
MethodPublicOutput,
|
|
34
|
+
NetworkState,
|
|
35
|
+
Protocol, ProtocolMethodExecutionContext,
|
|
36
|
+
ProtocolTransaction, ProvableStateTransition, RuntimeTransaction,
|
|
37
|
+
StateTransitionProver
|
|
38
|
+
} from "../src";
|
|
20
39
|
|
|
21
40
|
type BlockProverProofPair = [
|
|
22
41
|
Proof<void, MethodPublicOutput>,
|
|
23
42
|
Proof<StateTransitionProverPublicInput, StateTransitionProverPublicOutput>
|
|
24
43
|
];
|
|
25
44
|
|
|
45
|
+
class MockAppChain implements AreProofsEnabled {
|
|
46
|
+
public areProofsEnabled: boolean = false;
|
|
47
|
+
|
|
48
|
+
setProofsEnabled(areProofsEnabled: boolean): void {
|
|
49
|
+
this.areProofsEnabled = areProofsEnabled;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
class RuntimeZkProgrammable extends ZkProgrammable<
|
|
54
|
+
undefined,
|
|
55
|
+
MethodPublicOutput
|
|
56
|
+
> {
|
|
57
|
+
get appChain(): AreProofsEnabled | undefined {
|
|
58
|
+
return new MockAppChain();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
zkProgramFactory(): PlainZkProgram<undefined, MethodPublicOutput> {
|
|
62
|
+
const program = Experimental.ZkProgram({
|
|
63
|
+
publicOutput: MethodPublicOutput,
|
|
64
|
+
methods: {},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
compile: program.compile,
|
|
69
|
+
verify: program.verify,
|
|
70
|
+
methods: {},
|
|
71
|
+
Proof: ZkProgram.Proof(program),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
class RuntimeMock implements WithZkProgrammable<undefined, MethodPublicOutput> {
|
|
77
|
+
zkProgrammable: ZkProgrammable<undefined, MethodPublicOutput> =
|
|
78
|
+
new RuntimeZkProgrammable();
|
|
79
|
+
}
|
|
80
|
+
|
|
26
81
|
describe("blockProver", () => {
|
|
27
|
-
|
|
82
|
+
const networkState = new NetworkState({
|
|
83
|
+
block: {
|
|
84
|
+
height: UInt64.zero,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const protocol = Protocol.from({
|
|
89
|
+
modules: {
|
|
90
|
+
StateTransitionProver: StateTransitionProver,
|
|
91
|
+
BlockProver: BlockProver,
|
|
92
|
+
},
|
|
93
|
+
blockModules: [AccountStateModule],
|
|
94
|
+
});
|
|
28
95
|
|
|
29
96
|
beforeEach(() => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
);
|
|
35
|
-
container = childContainer;
|
|
97
|
+
protocol.registerValue({
|
|
98
|
+
StateTransitionWitnessProvider: new NoOpStateTransitionWitnessProvider(),
|
|
99
|
+
Runtime: new RuntimeMock(),
|
|
100
|
+
});
|
|
36
101
|
});
|
|
37
102
|
|
|
38
103
|
function generateTestProofs(
|
|
39
104
|
fromStateRoot: Field,
|
|
40
|
-
toStateRoot: Field
|
|
105
|
+
toStateRoot: Field,
|
|
106
|
+
protocolHash: Field,
|
|
107
|
+
tx: ProtocolTransaction,
|
|
108
|
+
networkState: NetworkState
|
|
41
109
|
): BlockProverProofPair {
|
|
42
|
-
const transactionHash =
|
|
110
|
+
const transactionHash =
|
|
111
|
+
RuntimeTransaction.fromProtocolTransaction(tx).hash();
|
|
43
112
|
const sthash = Field(123);
|
|
44
113
|
|
|
45
114
|
const appProof = new Proof<undefined, MethodPublicOutput>({
|
|
@@ -48,6 +117,7 @@ describe("blockProver", () => {
|
|
|
48
117
|
transactionHash,
|
|
49
118
|
stateTransitionsHash: sthash,
|
|
50
119
|
status: Bool(true),
|
|
120
|
+
networkStateHash: networkState.hash(),
|
|
51
121
|
}),
|
|
52
122
|
|
|
53
123
|
proof: "",
|
|
@@ -60,10 +130,12 @@ describe("blockProver", () => {
|
|
|
60
130
|
>({
|
|
61
131
|
publicInput: new StateTransitionProverPublicInput({
|
|
62
132
|
stateTransitionsHash: Field(0),
|
|
133
|
+
protocolTransitionsHash: Field(0),
|
|
63
134
|
stateRoot: fromStateRoot,
|
|
64
135
|
}),
|
|
65
136
|
publicOutput: new StateTransitionProverPublicOutput({
|
|
66
137
|
stateTransitionsHash: sthash,
|
|
138
|
+
protocolTransitionsHash: protocolHash,
|
|
67
139
|
stateRoot: toStateRoot,
|
|
68
140
|
}),
|
|
69
141
|
|
|
@@ -74,49 +146,80 @@ describe("blockProver", () => {
|
|
|
74
146
|
return [appProof, stProof];
|
|
75
147
|
}
|
|
76
148
|
|
|
77
|
-
it("should pass with
|
|
78
|
-
expect.assertions(
|
|
79
|
-
|
|
80
|
-
const blockProver = container.resolve(BlockProver);
|
|
149
|
+
it("previously applied transaction should also pass with derived publicInputs", () => {
|
|
150
|
+
expect.assertions(2);
|
|
81
151
|
|
|
82
|
-
const
|
|
83
|
-
const toState = Field(2);
|
|
152
|
+
const priv = PrivateKey.random();
|
|
84
153
|
|
|
85
|
-
const
|
|
154
|
+
const tx = new UnsignedTransaction({
|
|
155
|
+
methodId: Field(0),
|
|
156
|
+
args: [Field(0)],
|
|
157
|
+
nonce: UInt64.zero,
|
|
158
|
+
sender: priv.toPublicKey(),
|
|
159
|
+
})
|
|
160
|
+
.sign(priv)
|
|
161
|
+
.toProtocolTransaction();
|
|
86
162
|
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
163
|
+
const executionData = {
|
|
164
|
+
networkState,
|
|
165
|
+
transaction: tx,
|
|
90
166
|
};
|
|
91
|
-
blockProver.applyTransaction(state, stProof, appProof);
|
|
92
|
-
});
|
|
93
167
|
|
|
94
|
-
|
|
95
|
-
|
|
168
|
+
// const asmodule = protocol.resolve()
|
|
169
|
+
|
|
170
|
+
protocol.dependencyContainer
|
|
171
|
+
.resolveAll<BlockModule>("BlockModule")
|
|
172
|
+
.forEach((module) => {
|
|
173
|
+
module.createTransitions(executionData);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const hashList = new DefaultProvableHashList(ProvableStateTransition);
|
|
177
|
+
|
|
178
|
+
container
|
|
179
|
+
.resolve(ProtocolMethodExecutionContext)
|
|
180
|
+
.current()
|
|
181
|
+
.result.stateTransitions.map((x) => x.toProvable())
|
|
182
|
+
.forEach((st) => {
|
|
183
|
+
hashList.push(st);
|
|
184
|
+
});
|
|
96
185
|
|
|
97
|
-
const blockProver =
|
|
186
|
+
const blockProver = protocol.resolve("BlockProver");
|
|
98
187
|
|
|
99
188
|
const fromState = Field(1);
|
|
100
189
|
const toState = Field(2);
|
|
101
190
|
|
|
102
|
-
const [appProof, stProof] = generateTestProofs(
|
|
191
|
+
const [appProof, stProof] = generateTestProofs(
|
|
192
|
+
fromState,
|
|
193
|
+
toState,
|
|
194
|
+
hashList.commitment,
|
|
195
|
+
tx,
|
|
196
|
+
networkState
|
|
197
|
+
);
|
|
103
198
|
|
|
104
199
|
const fromProverState: BlockProverState = {
|
|
105
200
|
stateRoot: fromState,
|
|
106
201
|
transactionsHash: Field(0),
|
|
202
|
+
networkStateHash: networkState.hash(),
|
|
107
203
|
};
|
|
108
|
-
|
|
109
|
-
blockProver.applyTransaction(
|
|
204
|
+
|
|
205
|
+
const toProverState = blockProver.applyTransaction(
|
|
206
|
+
fromProverState,
|
|
207
|
+
stProof,
|
|
208
|
+
appProof,
|
|
209
|
+
executionData
|
|
210
|
+
);
|
|
110
211
|
|
|
111
212
|
const publicInput = new BlockProverPublicInput({
|
|
112
213
|
stateRoot: fromProverState.stateRoot,
|
|
113
214
|
transactionsHash: fromProverState.transactionsHash,
|
|
215
|
+
networkStateHash: networkState.hash(),
|
|
114
216
|
});
|
|
115
217
|
|
|
116
218
|
const publicOutput = blockProver.proveTransaction(
|
|
117
219
|
publicInput,
|
|
118
220
|
stProof,
|
|
119
|
-
appProof
|
|
221
|
+
appProof,
|
|
222
|
+
{ networkState, transaction: tx }
|
|
120
223
|
);
|
|
121
224
|
|
|
122
225
|
expect(publicOutput.stateRoot).toStrictEqual(toProverState.stateRoot);
|
package/test/Protocol.test.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import "reflect-metadata";
|
|
2
|
-
import { VanillaProtocol } from "../src/protocol/Protocol";
|
|
2
|
+
import { Protocol, VanillaProtocol } from "../src/protocol/Protocol";
|
|
3
3
|
import { beforeEach } from "@jest/globals";
|
|
4
4
|
import { BlockProver } from "../src/prover/block/BlockProver";
|
|
5
5
|
import { StateTransitionProver } from "../src/prover/statetransition/StateTransitionProver";
|
|
6
|
-
import { NoOpStateTransitionWitnessProvider } from "../src";
|
|
6
|
+
import { NoOpStateTransitionWitnessProvider, ProvableTransactionHook } from "../src";
|
|
7
|
+
import { AccountStateModule } from "../src/blockmodules/AccountStateModule";
|
|
7
8
|
|
|
8
9
|
describe("protocol", () => {
|
|
9
|
-
let protocol: ReturnType<typeof VanillaProtocol.create>;
|
|
10
|
-
|
|
11
10
|
beforeEach(() => {
|
|
12
|
-
protocol = VanillaProtocol.create();
|
|
13
11
|
});
|
|
14
12
|
|
|
15
13
|
it("should resolve all provers correctly", async () => {
|
|
16
14
|
expect.assertions(2);
|
|
17
15
|
|
|
16
|
+
const protocol = VanillaProtocol.create();
|
|
17
|
+
|
|
18
18
|
protocol.dependencyContainer.register("StateTransitionWitnessProvider", {
|
|
19
19
|
useValue: new NoOpStateTransitionWitnessProvider()
|
|
20
20
|
})
|
|
@@ -24,4 +24,21 @@ describe("protocol", () => {
|
|
|
24
24
|
protocol.stateTransitionProver instanceof StateTransitionProver
|
|
25
25
|
).toBe(true);
|
|
26
26
|
});
|
|
27
|
+
|
|
28
|
+
it.only("should initialize hooks correctly", () => {
|
|
29
|
+
expect.assertions(2);
|
|
30
|
+
|
|
31
|
+
const protocol = Protocol.from({
|
|
32
|
+
modules: {
|
|
33
|
+
BlockProver,
|
|
34
|
+
StateTransitionProver,
|
|
35
|
+
AccountStateModule,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const hooks = protocol.dependencyContainer.resolveAll<ProvableTransactionHook>("ProvableTransactionHook")
|
|
40
|
+
|
|
41
|
+
expect(hooks).toHaveLength(1);
|
|
42
|
+
expect(hooks[0].name).toBe("AccountStateModule");
|
|
43
|
+
})
|
|
27
44
|
});
|
|
@@ -20,7 +20,7 @@ describe("stateTransition", () => {
|
|
|
20
20
|
tree: RollupMerkleTree,
|
|
21
21
|
transitions: ProvableStateTransition[]
|
|
22
22
|
) {
|
|
23
|
-
const batch = StateTransitionProvableBatch.fromTransitions(transitions);
|
|
23
|
+
const batch = StateTransitionProvableBatch.fromTransitions(transitions, []);
|
|
24
24
|
|
|
25
25
|
const temporaryTree = new RollupMerkleTree(
|
|
26
26
|
new CachedMerkleTreeStore(tree.store)
|