@proto-kit/protocol 0.1.1-develop.1086
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/LICENSE.md +201 -0
- package/README.md +45 -0
- package/dist/Constants.d.ts +4 -0
- package/dist/Constants.d.ts.map +1 -0
- package/dist/Constants.js +3 -0
- package/dist/hooks/AccountStateHook.d.ts +52 -0
- package/dist/hooks/AccountStateHook.d.ts.map +1 -0
- package/dist/hooks/AccountStateHook.js +47 -0
- package/dist/hooks/BlockHeightHook.d.ts +7 -0
- package/dist/hooks/BlockHeightHook.d.ts.map +1 -0
- package/dist/hooks/BlockHeightHook.js +15 -0
- package/dist/hooks/LastStateRootBlockHook.d.ts +8 -0
- package/dist/hooks/LastStateRootBlockHook.d.ts.map +1 -0
- package/dist/hooks/LastStateRootBlockHook.js +15 -0
- package/dist/hooks/NoopBlockHook.d.ts +9 -0
- package/dist/hooks/NoopBlockHook.d.ts.map +1 -0
- package/dist/hooks/NoopBlockHook.js +9 -0
- package/dist/hooks/NoopSettlementHook.d.ts +6 -0
- package/dist/hooks/NoopSettlementHook.d.ts.map +1 -0
- package/dist/hooks/NoopSettlementHook.js +17 -0
- package/dist/hooks/NoopTransactionHook.d.ts +6 -0
- package/dist/hooks/NoopTransactionHook.d.ts.map +1 -0
- package/dist/hooks/NoopTransactionHook.js +7 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/model/MethodPublicOutput.d.ts +113 -0
- package/dist/model/MethodPublicOutput.d.ts.map +1 -0
- package/dist/model/MethodPublicOutput.js +14 -0
- package/dist/model/Option.d.ts +122 -0
- package/dist/model/Option.d.ts.map +1 -0
- package/dist/model/Option.js +110 -0
- package/dist/model/Path.d.ts +31 -0
- package/dist/model/Path.d.ts.map +1 -0
- package/dist/model/Path.js +42 -0
- package/dist/model/RuntimeLike.d.ts +11 -0
- package/dist/model/RuntimeLike.d.ts.map +1 -0
- package/dist/model/RuntimeLike.js +1 -0
- package/dist/model/StateTransition.d.ts +135 -0
- package/dist/model/StateTransition.d.ts.map +1 -0
- package/dist/model/StateTransition.js +68 -0
- package/dist/model/StateTransitionProvableBatch.d.ts +172 -0
- package/dist/model/StateTransitionProvableBatch.d.ts.map +1 -0
- package/dist/model/StateTransitionProvableBatch.js +85 -0
- package/dist/model/network/NetworkState.d.ts +160 -0
- package/dist/model/network/NetworkState.d.ts.map +1 -0
- package/dist/model/network/NetworkState.js +31 -0
- package/dist/model/transaction/RuntimeTransaction.d.ts +122 -0
- package/dist/model/transaction/RuntimeTransaction.d.ts.map +1 -0
- package/dist/model/transaction/RuntimeTransaction.js +86 -0
- package/dist/model/transaction/SignedTransaction.d.ts +107 -0
- package/dist/model/transaction/SignedTransaction.d.ts.map +1 -0
- package/dist/model/transaction/SignedTransaction.js +33 -0
- package/dist/model/transaction/ValueOption.d.ts +173 -0
- package/dist/model/transaction/ValueOption.d.ts.map +1 -0
- package/dist/model/transaction/ValueOption.js +24 -0
- package/dist/protocol/Protocol.d.ts +43 -0
- package/dist/protocol/Protocol.d.ts.map +1 -0
- package/dist/protocol/Protocol.js +95 -0
- package/dist/protocol/ProtocolEnvironment.d.ts +9 -0
- package/dist/protocol/ProtocolEnvironment.d.ts.map +1 -0
- package/dist/protocol/ProtocolEnvironment.js +1 -0
- package/dist/protocol/ProtocolModule.d.ts +9 -0
- package/dist/protocol/ProtocolModule.d.ts.map +1 -0
- package/dist/protocol/ProtocolModule.js +12 -0
- package/dist/protocol/ProvableBlockHook.d.ts +8 -0
- package/dist/protocol/ProvableBlockHook.d.ts.map +1 -0
- package/dist/protocol/ProvableBlockHook.js +4 -0
- package/dist/protocol/ProvableTransactionHook.d.ts +7 -0
- package/dist/protocol/ProvableTransactionHook.d.ts.map +1 -0
- package/dist/protocol/ProvableTransactionHook.js +3 -0
- package/dist/protocol/TransitioningProtocolModule.d.ts +10 -0
- package/dist/protocol/TransitioningProtocolModule.d.ts.map +1 -0
- package/dist/protocol/TransitioningProtocolModule.js +8 -0
- package/dist/prover/block/BlockProvable.d.ts +395 -0
- package/dist/prover/block/BlockProvable.d.ts.map +1 -0
- package/dist/prover/block/BlockProvable.js +45 -0
- package/dist/prover/block/BlockProver.d.ts +92 -0
- package/dist/prover/block/BlockProver.d.ts.map +1 -0
- package/dist/prover/block/BlockProver.js +472 -0
- package/dist/prover/block/accummulators/BlockHashMerkleTree.d.ts +64 -0
- package/dist/prover/block/accummulators/BlockHashMerkleTree.d.ts.map +1 -0
- package/dist/prover/block/accummulators/BlockHashMerkleTree.js +16 -0
- package/dist/prover/block/accummulators/RuntimeVerificationKeyTree.d.ts +139 -0
- package/dist/prover/block/accummulators/RuntimeVerificationKeyTree.d.ts.map +1 -0
- package/dist/prover/block/accummulators/RuntimeVerificationKeyTree.js +20 -0
- package/dist/prover/block/services/RuntimeVerificationKeyRootService.d.ts +7 -0
- package/dist/prover/block/services/RuntimeVerificationKeyRootService.d.ts.map +1 -0
- package/dist/prover/block/services/RuntimeVerificationKeyRootService.js +22 -0
- package/dist/prover/statetransition/StateTransitionProvable.d.ts +174 -0
- package/dist/prover/statetransition/StateTransitionProvable.d.ts.map +1 -0
- package/dist/prover/statetransition/StateTransitionProvable.js +15 -0
- package/dist/prover/statetransition/StateTransitionProver.d.ts +51 -0
- package/dist/prover/statetransition/StateTransitionProver.d.ts.map +1 -0
- package/dist/prover/statetransition/StateTransitionProver.js +188 -0
- package/dist/prover/statetransition/StateTransitionWitnessProvider.d.ts +16 -0
- package/dist/prover/statetransition/StateTransitionWitnessProvider.d.ts.map +1 -0
- package/dist/prover/statetransition/StateTransitionWitnessProvider.js +16 -0
- package/dist/prover/statetransition/StateTransitionWitnessProviderReference.d.ts +7 -0
- package/dist/prover/statetransition/StateTransitionWitnessProviderReference.d.ts.map +1 -0
- package/dist/prover/statetransition/StateTransitionWitnessProviderReference.js +19 -0
- package/dist/settlement/ContractModule.d.ts +15 -0
- package/dist/settlement/ContractModule.d.ts.map +1 -0
- package/dist/settlement/ContractModule.js +11 -0
- package/dist/settlement/SettlementContractModule.d.ts +40 -0
- package/dist/settlement/SettlementContractModule.d.ts.map +1 -0
- package/dist/settlement/SettlementContractModule.js +71 -0
- package/dist/settlement/contracts/DispatchContractProtocolModule.d.ts +12 -0
- package/dist/settlement/contracts/DispatchContractProtocolModule.d.ts.map +1 -0
- package/dist/settlement/contracts/DispatchContractProtocolModule.js +35 -0
- package/dist/settlement/contracts/DispatchSmartContract.d.ts +22 -0
- package/dist/settlement/contracts/DispatchSmartContract.d.ts.map +1 -0
- package/dist/settlement/contracts/DispatchSmartContract.js +110 -0
- package/dist/settlement/contracts/SettlementContractProtocolModule.d.ts +19 -0
- package/dist/settlement/contracts/SettlementContractProtocolModule.d.ts.map +1 -0
- package/dist/settlement/contracts/SettlementContractProtocolModule.js +44 -0
- package/dist/settlement/contracts/SettlementSmartContract.d.ts +42 -0
- package/dist/settlement/contracts/SettlementSmartContract.d.ts.map +1 -0
- package/dist/settlement/contracts/SettlementSmartContract.js +241 -0
- package/dist/settlement/messages/Deposit.d.ts +64 -0
- package/dist/settlement/messages/Deposit.d.ts.map +1 -0
- package/dist/settlement/messages/Deposit.js +6 -0
- package/dist/settlement/messages/OutgoingMessageArgument.d.ts +189 -0
- package/dist/settlement/messages/OutgoingMessageArgument.d.ts.map +1 -0
- package/dist/settlement/messages/OutgoingMessageArgument.js +32 -0
- package/dist/settlement/messages/Withdrawal.d.ts +65 -0
- package/dist/settlement/messages/Withdrawal.d.ts.map +1 -0
- package/dist/settlement/messages/Withdrawal.js +13 -0
- package/dist/settlement/modularity/ProvableSettlementHook.d.ts +24 -0
- package/dist/settlement/modularity/ProvableSettlementHook.d.ts.map +1 -0
- package/dist/settlement/modularity/ProvableSettlementHook.js +3 -0
- package/dist/settlement/modules/NetworkStateSettlementModule.d.ts +11 -0
- package/dist/settlement/modules/NetworkStateSettlementModule.d.ts.map +1 -0
- package/dist/settlement/modules/NetworkStateSettlementModule.js +14 -0
- package/dist/state/State.d.ts +68 -0
- package/dist/state/State.d.ts.map +1 -0
- package/dist/state/State.js +129 -0
- package/dist/state/StateMap.d.ts +37 -0
- package/dist/state/StateMap.d.ts.map +1 -0
- package/dist/state/StateMap.js +55 -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 +8 -0
- package/dist/state/StateServiceProvider.d.ts.map +1 -0
- package/dist/state/StateServiceProvider.js +36 -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 +30 -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 +193 -0
- package/dist/state/context/RuntimeMethodExecutionContext.d.ts.map +1 -0
- package/dist/state/context/RuntimeMethodExecutionContext.js +135 -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 +5 -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 +39 -0
- package/dist/utils/MinaPrefixedProvableHashList.d.ts +24 -0
- package/dist/utils/MinaPrefixedProvableHashList.d.ts.map +1 -0
- package/dist/utils/MinaPrefixedProvableHashList.js +52 -0
- package/dist/utils/PrefixedProvableHashList.d.ts +8 -0
- package/dist/utils/PrefixedProvableHashList.d.ts.map +1 -0
- package/dist/utils/PrefixedProvableHashList.js +12 -0
- package/dist/utils/ProvableHashList.d.ts +27 -0
- package/dist/utils/ProvableHashList.d.ts.map +1 -0
- package/dist/utils/ProvableHashList.js +43 -0
- package/dist/utils/ProvableReductionHashList.d.ts +14 -0
- package/dist/utils/ProvableReductionHashList.d.ts.map +1 -0
- package/dist/utils/ProvableReductionHashList.js +50 -0
- package/dist/utils/StateTransitionReductionList.d.ts +11 -0
- package/dist/utils/StateTransitionReductionList.d.ts.map +1 -0
- package/dist/utils/StateTransitionReductionList.js +60 -0
- package/dist/utils/utils.d.ts +11 -0
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/utils/utils.js +44 -0
- package/jest.config.cjs +1 -0
- package/package.json +36 -0
- package/src/Constants.ts +3 -0
- package/src/hooks/AccountStateHook.ts +48 -0
- package/src/hooks/BlockHeightHook.ts +17 -0
- package/src/hooks/LastStateRootBlockHook.ts +26 -0
- package/src/hooks/NoopBlockHook.ts +21 -0
- package/src/hooks/NoopSettlementHook.ts +20 -0
- package/src/hooks/NoopTransactionHook.ts +10 -0
- package/src/index.ts +53 -0
- package/src/model/MethodPublicOutput.ts +14 -0
- package/src/model/Option.ts +172 -0
- package/src/model/Path.ts +50 -0
- package/src/model/RuntimeLike.ts +12 -0
- package/src/model/StateTransition.ts +88 -0
- package/src/model/StateTransitionProvableBatch.ts +125 -0
- package/src/model/Transaction.ts +31 -0
- package/src/model/network/NetworkState.ts +33 -0
- package/src/model/transaction/RuntimeTransaction.ts +105 -0
- package/src/model/transaction/SignedTransaction.ts +47 -0
- package/src/model/transaction/ValueOption.ts +28 -0
- package/src/protocol/Protocol.ts +197 -0
- package/src/protocol/ProtocolEnvironment.ts +10 -0
- package/src/protocol/ProtocolModule.ts +27 -0
- package/src/protocol/ProvableBlockHook.ts +19 -0
- package/src/protocol/ProvableTransactionHook.ts +13 -0
- package/src/protocol/TransitioningProtocolModule.ts +12 -0
- package/src/prover/block/BlockProvable.ts +99 -0
- package/src/prover/block/BlockProver.ts +954 -0
- package/src/prover/block/accummulators/BlockHashMerkleTree.ts +16 -0
- package/src/prover/block/accummulators/RuntimeVerificationKeyTree.ts +24 -0
- package/src/prover/block/services/RuntimeVerificationKeyRootService.ts +20 -0
- package/src/prover/statetransition/StateTransitionProvable.ts +44 -0
- package/src/prover/statetransition/StateTransitionProver.ts +371 -0
- package/src/prover/statetransition/StateTransitionWitnessProvider.ts +23 -0
- package/src/prover/statetransition/StateTransitionWitnessProviderReference.ts +17 -0
- package/src/settlement/ContractModule.ts +24 -0
- package/src/settlement/SettlementContractModule.ts +132 -0
- package/src/settlement/contracts/DispatchContractProtocolModule.ts +39 -0
- package/src/settlement/contracts/DispatchSmartContract.ts +136 -0
- package/src/settlement/contracts/SettlementContractProtocolModule.ts +67 -0
- package/src/settlement/contracts/SettlementSmartContract.ts +344 -0
- package/src/settlement/messages/Deposit.ts +6 -0
- package/src/settlement/messages/OutgoingMessageArgument.ts +42 -0
- package/src/settlement/messages/Withdrawal.ts +14 -0
- package/src/settlement/modularity/ProvableSettlementHook.ts +33 -0
- package/src/settlement/modules/NetworkStateSettlementModule.ts +42 -0
- package/src/state/State.ts +175 -0
- package/src/state/StateMap.ts +73 -0
- package/src/state/StateService.ts +6 -0
- package/src/state/StateServiceProvider.ts +37 -0
- package/src/state/assert/assert.ts +35 -0
- package/src/state/context/RuntimeMethodExecutionContext.ts +174 -0
- package/src/state/context/TransitionMethodExecutionContext.ts +26 -0
- package/src/state/protocol/ProtocolState.ts +61 -0
- package/src/utils/MinaPrefixedProvableHashList.ts +73 -0
- package/src/utils/PrefixedProvableHashList.ts +21 -0
- package/src/utils/ProvableHashList.ts +50 -0
- package/src/utils/ProvableReductionHashList.ts +68 -0
- package/src/utils/StateTransitionReductionList.ts +89 -0
- package/src/utils/utils.ts +75 -0
- package/test/BlockProver.test.ts +211 -0
- package/test/Protocol.test.ts +37 -0
- package/test/State.test.ts +45 -0
- package/test/StateTransition.test.ts +174 -0
- package/test/TestingProtocol.ts +47 -0
- package/test/model/Option.test.ts +72 -0
- package/test/state/assert/assert.test.ts +56 -0
- package/test/tsconfig.json +7 -0
- package/test/utils/ProvableReductionHashList.test.ts +117 -0
- package/test/utils.test.ts +27 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,954 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Bool,
|
|
3
|
+
DynamicProof,
|
|
4
|
+
Field,
|
|
5
|
+
Poseidon,
|
|
6
|
+
Proof,
|
|
7
|
+
Provable,
|
|
8
|
+
SelfProof,
|
|
9
|
+
VerificationKey,
|
|
10
|
+
ZkProgram,
|
|
11
|
+
} from "o1js";
|
|
12
|
+
import { container, inject, injectable, injectAll } from "tsyringe";
|
|
13
|
+
import {
|
|
14
|
+
AreProofsEnabled,
|
|
15
|
+
PlainZkProgram,
|
|
16
|
+
provableMethod,
|
|
17
|
+
WithZkProgrammable,
|
|
18
|
+
ZkProgrammable,
|
|
19
|
+
} from "@proto-kit/common";
|
|
20
|
+
|
|
21
|
+
import { DefaultProvableHashList } from "../../utils/ProvableHashList";
|
|
22
|
+
import { MethodPublicOutput } from "../../model/MethodPublicOutput";
|
|
23
|
+
import { ProtocolModule } from "../../protocol/ProtocolModule";
|
|
24
|
+
import {
|
|
25
|
+
StateTransitionProof,
|
|
26
|
+
StateTransitionProverPublicInput,
|
|
27
|
+
StateTransitionProverPublicOutput,
|
|
28
|
+
} from "../statetransition/StateTransitionProvable";
|
|
29
|
+
import { RuntimeTransaction } from "../../model/transaction/RuntimeTransaction";
|
|
30
|
+
import {
|
|
31
|
+
ProvableStateTransition,
|
|
32
|
+
StateTransition,
|
|
33
|
+
} from "../../model/StateTransition";
|
|
34
|
+
import { ProvableTransactionHook } from "../../protocol/ProvableTransactionHook";
|
|
35
|
+
import { RuntimeMethodExecutionContext } from "../../state/context/RuntimeMethodExecutionContext";
|
|
36
|
+
import { ProvableBlockHook } from "../../protocol/ProvableBlockHook";
|
|
37
|
+
import { NetworkState } from "../../model/network/NetworkState";
|
|
38
|
+
import { SignedTransaction } from "../../model/transaction/SignedTransaction";
|
|
39
|
+
import {
|
|
40
|
+
MinaActions,
|
|
41
|
+
MinaActionsHashList,
|
|
42
|
+
} from "../../utils/MinaPrefixedProvableHashList";
|
|
43
|
+
import { StateTransitionReductionList } from "../../utils/StateTransitionReductionList";
|
|
44
|
+
|
|
45
|
+
import {
|
|
46
|
+
BlockProvable,
|
|
47
|
+
BlockProverExecutionData,
|
|
48
|
+
BlockProverProof,
|
|
49
|
+
BlockProverPublicInput,
|
|
50
|
+
BlockProverPublicOutput,
|
|
51
|
+
DynamicRuntimeProof,
|
|
52
|
+
} from "./BlockProvable";
|
|
53
|
+
import {
|
|
54
|
+
BlockHashMerkleTreeWitness,
|
|
55
|
+
BlockHashTreeEntry,
|
|
56
|
+
} from "./accummulators/BlockHashMerkleTree";
|
|
57
|
+
import {
|
|
58
|
+
MethodVKConfigData,
|
|
59
|
+
MinimalVKTreeService,
|
|
60
|
+
RuntimeVerificationKeyAttestation,
|
|
61
|
+
} from "./accummulators/RuntimeVerificationKeyTree";
|
|
62
|
+
import { RuntimeVerificationKeyRootService } from "./services/RuntimeVerificationKeyRootService";
|
|
63
|
+
|
|
64
|
+
const errors = {
|
|
65
|
+
stateProofNotStartingAtZero: () =>
|
|
66
|
+
"StateProof not starting ST-commitment at zero",
|
|
67
|
+
|
|
68
|
+
stateTransitionsHashNotEqual: () =>
|
|
69
|
+
"StateTransition list commitments are not equal",
|
|
70
|
+
|
|
71
|
+
propertyNotMatchingStep: (propertyName: string, step: string) =>
|
|
72
|
+
`${propertyName} not matching: ${step}`,
|
|
73
|
+
|
|
74
|
+
propertyNotMatching: (propertyName: string) => `${propertyName} not matching`,
|
|
75
|
+
|
|
76
|
+
stateRootNotMatching: (step: string) =>
|
|
77
|
+
errors.propertyNotMatchingStep("StateRoots", step),
|
|
78
|
+
|
|
79
|
+
transactionsHashNotMatching: (step: string) =>
|
|
80
|
+
errors.propertyNotMatchingStep("Transactions hash", step),
|
|
81
|
+
|
|
82
|
+
networkStateHashNotMatching: (step: string) =>
|
|
83
|
+
errors.propertyNotMatchingStep("Network state hash", step),
|
|
84
|
+
|
|
85
|
+
invalidZkProgramTreeRoot: () =>
|
|
86
|
+
"Root hash of the provided zkProgram config witness is invalid",
|
|
87
|
+
|
|
88
|
+
invalidZkProgramConfigMethodId: () =>
|
|
89
|
+
"Method id of the provided zkProgram config does not match the executed transaction method id",
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Should be equal to BlockProver.PublicInput
|
|
93
|
+
export interface BlockProverState {
|
|
94
|
+
/**
|
|
95
|
+
* The current state root of the block prover
|
|
96
|
+
*/
|
|
97
|
+
stateRoot: Field;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* The current commitment of the transaction-list which
|
|
101
|
+
* will at the end equal the bundle hash
|
|
102
|
+
*/
|
|
103
|
+
transactionsHash: Field;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The network state which gives access to values such as blockHeight
|
|
107
|
+
* This value is the same for the whole batch (L2 block)
|
|
108
|
+
*/
|
|
109
|
+
networkStateHash: Field;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The root of the merkle tree encoding all block hashes,
|
|
113
|
+
* see `BlockHashMerkleTree`
|
|
114
|
+
*/
|
|
115
|
+
blockHashRoot: Field;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* A variant of the transactionsHash that is never reset.
|
|
119
|
+
* Thought for usage in the sequence state mempool.
|
|
120
|
+
* In comparison, transactionsHash restarts at 0 for every new block
|
|
121
|
+
*/
|
|
122
|
+
eternalTransactionsHash: Field;
|
|
123
|
+
|
|
124
|
+
incomingMessagesHash: Field;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function maxField() {
|
|
128
|
+
return Field(Field.ORDER - 1n);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export type BlockProof = Proof<BlockProverPublicInput, BlockProverPublicOutput>;
|
|
132
|
+
export type RuntimeProof = Proof<void, MethodPublicOutput>;
|
|
133
|
+
|
|
134
|
+
export class BlockProverProgrammable extends ZkProgrammable<
|
|
135
|
+
BlockProverPublicInput,
|
|
136
|
+
BlockProverPublicOutput
|
|
137
|
+
> {
|
|
138
|
+
public constructor(
|
|
139
|
+
private readonly prover: BlockProver,
|
|
140
|
+
public readonly stateTransitionProver: ZkProgrammable<
|
|
141
|
+
StateTransitionProverPublicInput,
|
|
142
|
+
StateTransitionProverPublicOutput
|
|
143
|
+
>,
|
|
144
|
+
public readonly runtime: ZkProgrammable<undefined, MethodPublicOutput>,
|
|
145
|
+
private readonly transactionHooks: ProvableTransactionHook<unknown>[],
|
|
146
|
+
private readonly blockHooks: ProvableBlockHook<unknown>[],
|
|
147
|
+
private readonly verificationKeyService: MinimalVKTreeService
|
|
148
|
+
) {
|
|
149
|
+
super();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
public get appChain(): AreProofsEnabled | undefined {
|
|
153
|
+
return this.prover.appChain;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Applies and checks the two proofs and applies the corresponding state
|
|
158
|
+
* changes to the given state
|
|
159
|
+
*
|
|
160
|
+
* @param state The from-state of the BlockProver
|
|
161
|
+
* @param stateTransitionProof
|
|
162
|
+
* @param runtimeProof
|
|
163
|
+
* @param executionData
|
|
164
|
+
* @param verificationKey
|
|
165
|
+
* @returns The new BlockProver-state to be used as public output
|
|
166
|
+
*/
|
|
167
|
+
public async applyTransaction(
|
|
168
|
+
state: BlockProverState,
|
|
169
|
+
stateTransitionProof: Proof<
|
|
170
|
+
StateTransitionProverPublicInput,
|
|
171
|
+
StateTransitionProverPublicOutput
|
|
172
|
+
>,
|
|
173
|
+
runtimeProof: DynamicRuntimeProof,
|
|
174
|
+
executionData: BlockProverExecutionData,
|
|
175
|
+
verificationKey: VerificationKey
|
|
176
|
+
): Promise<BlockProverState> {
|
|
177
|
+
const { transaction, networkState, signature } = executionData;
|
|
178
|
+
|
|
179
|
+
const { isMessage } = runtimeProof.publicOutput;
|
|
180
|
+
|
|
181
|
+
runtimeProof.verify(verificationKey);
|
|
182
|
+
stateTransitionProof.verify();
|
|
183
|
+
|
|
184
|
+
const stateTo = { ...state };
|
|
185
|
+
|
|
186
|
+
// Checks for the stateTransitionProof and appProof matching
|
|
187
|
+
stateTransitionProof.publicInput.stateTransitionsHash.assertEquals(
|
|
188
|
+
Field(0),
|
|
189
|
+
errors.stateProofNotStartingAtZero()
|
|
190
|
+
);
|
|
191
|
+
stateTransitionProof.publicInput.protocolTransitionsHash.assertEquals(
|
|
192
|
+
Field(0),
|
|
193
|
+
errors.stateProofNotStartingAtZero()
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
runtimeProof.publicOutput.stateTransitionsHash.assertEquals(
|
|
197
|
+
stateTransitionProof.publicOutput.stateTransitionsHash,
|
|
198
|
+
errors.stateTransitionsHashNotEqual()
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
// Assert from state roots
|
|
202
|
+
state.stateRoot.assertEquals(
|
|
203
|
+
stateTransitionProof.publicInput.stateRoot,
|
|
204
|
+
errors.propertyNotMatching("from state root")
|
|
205
|
+
);
|
|
206
|
+
state.stateRoot.assertEquals(
|
|
207
|
+
stateTransitionProof.publicInput.protocolStateRoot,
|
|
208
|
+
errors.propertyNotMatching("from protocol state root")
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
// Apply protocol state transitions
|
|
212
|
+
await this.assertProtocolTransitions(
|
|
213
|
+
stateTransitionProof,
|
|
214
|
+
executionData,
|
|
215
|
+
runtimeProof
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
// Apply state if status success
|
|
219
|
+
stateTo.stateRoot = Provable.if(
|
|
220
|
+
runtimeProof.publicOutput.status,
|
|
221
|
+
stateTransitionProof.publicOutput.stateRoot,
|
|
222
|
+
stateTransitionProof.publicOutput.protocolStateRoot
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
// Check transaction integrity against appProof
|
|
226
|
+
const blockTransactionHash = transaction.hash();
|
|
227
|
+
|
|
228
|
+
blockTransactionHash.assertEquals(
|
|
229
|
+
runtimeProof.publicOutput.transactionHash,
|
|
230
|
+
"Transactions provided in AppProof and BlockProof do not match"
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
// Check transaction signature
|
|
234
|
+
new SignedTransaction({
|
|
235
|
+
transaction,
|
|
236
|
+
signature,
|
|
237
|
+
})
|
|
238
|
+
.validateSignature()
|
|
239
|
+
.or(isMessage)
|
|
240
|
+
.assertTrue("Transaction signature not valid");
|
|
241
|
+
|
|
242
|
+
// Validate layout of transaction witness
|
|
243
|
+
transaction.assertTransactionType(isMessage);
|
|
244
|
+
|
|
245
|
+
// Check network state integrity against appProof
|
|
246
|
+
state.networkStateHash.assertEquals(
|
|
247
|
+
runtimeProof.publicOutput.networkStateHash,
|
|
248
|
+
"Network state does not match state used in AppProof"
|
|
249
|
+
);
|
|
250
|
+
state.networkStateHash.assertEquals(
|
|
251
|
+
networkState.hash(),
|
|
252
|
+
"Network state provided to BlockProver does not match the publicInput"
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
return stateTo;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// eslint-disable-next-line max-len
|
|
259
|
+
// TODO How does this interact with the RuntimeMethodExecutionContext when executing runtimemethods?
|
|
260
|
+
|
|
261
|
+
public async assertProtocolTransitions(
|
|
262
|
+
stateTransitionProof: Proof<
|
|
263
|
+
StateTransitionProverPublicInput,
|
|
264
|
+
StateTransitionProverPublicOutput
|
|
265
|
+
>,
|
|
266
|
+
executionData: BlockProverExecutionData,
|
|
267
|
+
runtimeProof: DynamicProof<void, MethodPublicOutput>
|
|
268
|
+
) {
|
|
269
|
+
const executionContext = container.resolve(RuntimeMethodExecutionContext);
|
|
270
|
+
executionContext.clear();
|
|
271
|
+
|
|
272
|
+
// Setup context for potential calls to runtime methods.
|
|
273
|
+
// This way they can use this.transaction etc. while still having provable
|
|
274
|
+
// integrity between data
|
|
275
|
+
executionContext.setup({
|
|
276
|
+
// That is why we should probably hide it from the transaction context inputs
|
|
277
|
+
transaction: executionData.transaction,
|
|
278
|
+
networkState: executionData.networkState,
|
|
279
|
+
});
|
|
280
|
+
executionContext.beforeMethod("", "", []);
|
|
281
|
+
|
|
282
|
+
for (const module of this.transactionHooks) {
|
|
283
|
+
// eslint-disable-next-line no-await-in-loop
|
|
284
|
+
await module.onTransaction(executionData);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
executionContext.afterMethod();
|
|
288
|
+
|
|
289
|
+
const { stateTransitions, status, statusMessage } =
|
|
290
|
+
executionContext.current().result;
|
|
291
|
+
|
|
292
|
+
status.assertTrue(statusMessage);
|
|
293
|
+
|
|
294
|
+
const transitions = stateTransitions.map((transition) =>
|
|
295
|
+
transition.toProvable()
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
const hashList = new StateTransitionReductionList(
|
|
299
|
+
ProvableStateTransition,
|
|
300
|
+
stateTransitionProof.publicInput.protocolTransitionsHash
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
transitions.forEach((transition) => {
|
|
304
|
+
hashList.push(transition);
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
stateTransitionProof.publicOutput.protocolTransitionsHash.assertEquals(
|
|
308
|
+
hashList.commitment,
|
|
309
|
+
"ProtocolTransitionsHash not matching the generated protocol transitions"
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
private async executeBlockHooks(
|
|
314
|
+
state: BlockProverState,
|
|
315
|
+
inputNetworkState: NetworkState,
|
|
316
|
+
type: "afterBlock" | "beforeBlock"
|
|
317
|
+
): Promise<{
|
|
318
|
+
networkState: NetworkState;
|
|
319
|
+
stateTransitions: StateTransition<unknown>[];
|
|
320
|
+
}> {
|
|
321
|
+
const executionContext = container.resolve(RuntimeMethodExecutionContext);
|
|
322
|
+
executionContext.clear();
|
|
323
|
+
executionContext.beforeMethod("", "", []);
|
|
324
|
+
|
|
325
|
+
const resultingNetworkState = await this.blockHooks.reduce<
|
|
326
|
+
Promise<NetworkState>
|
|
327
|
+
>(async (networkStatePromise, blockHook) => {
|
|
328
|
+
const networkState = await networkStatePromise;
|
|
329
|
+
// Setup context for potential calls to runtime methods.
|
|
330
|
+
// With the special case that we set the new networkstate for every hook
|
|
331
|
+
// We also have to put in a dummy transaction for network.transaction
|
|
332
|
+
executionContext.setup({
|
|
333
|
+
transaction: RuntimeTransaction.dummyTransaction(),
|
|
334
|
+
networkState,
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
if (type === "beforeBlock") {
|
|
338
|
+
return await blockHook.beforeBlock(networkState, state);
|
|
339
|
+
}
|
|
340
|
+
if (type === "afterBlock") {
|
|
341
|
+
return await blockHook.afterBlock(networkState, state);
|
|
342
|
+
}
|
|
343
|
+
throw new Error("Unreachable");
|
|
344
|
+
}, Promise.resolve(inputNetworkState));
|
|
345
|
+
|
|
346
|
+
executionContext.afterMethod();
|
|
347
|
+
|
|
348
|
+
const { stateTransitions, status, statusMessage } =
|
|
349
|
+
executionContext.current().result;
|
|
350
|
+
|
|
351
|
+
status.assertTrue(`Block hook call failed: ${statusMessage ?? "-"}`);
|
|
352
|
+
|
|
353
|
+
return {
|
|
354
|
+
networkState: resultingNetworkState,
|
|
355
|
+
stateTransitions,
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
private addTransactionToBundle(
|
|
360
|
+
state: BlockProverState,
|
|
361
|
+
isMessage: Bool,
|
|
362
|
+
transaction: RuntimeTransaction
|
|
363
|
+
): BlockProverState {
|
|
364
|
+
const stateTo = {
|
|
365
|
+
...state,
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
const transactionHash = transaction.hash();
|
|
369
|
+
|
|
370
|
+
// Append tx to transaction list
|
|
371
|
+
const transactionList = new DefaultProvableHashList(
|
|
372
|
+
Field,
|
|
373
|
+
state.transactionsHash
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
transactionList.pushIf(transactionHash, isMessage.not());
|
|
377
|
+
stateTo.transactionsHash = transactionList.commitment;
|
|
378
|
+
|
|
379
|
+
// Append tx to eternal transaction list
|
|
380
|
+
// TODO Change that to the a sequence-state compatible transaction struct
|
|
381
|
+
const eternalTransactionList = new DefaultProvableHashList(
|
|
382
|
+
Field,
|
|
383
|
+
state.eternalTransactionsHash
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
eternalTransactionList.pushIf(transactionHash, isMessage.not());
|
|
387
|
+
stateTo.eternalTransactionsHash = eternalTransactionList.commitment;
|
|
388
|
+
|
|
389
|
+
// Append tx to incomingMessagesHash
|
|
390
|
+
const actionHash = MinaActions.actionHash(transaction.hashData());
|
|
391
|
+
|
|
392
|
+
const incomingMessagesList = new MinaActionsHashList(
|
|
393
|
+
state.incomingMessagesHash
|
|
394
|
+
);
|
|
395
|
+
incomingMessagesList.pushIf(actionHash, isMessage);
|
|
396
|
+
|
|
397
|
+
stateTo.incomingMessagesHash = incomingMessagesList.commitment;
|
|
398
|
+
|
|
399
|
+
return stateTo;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
@provableMethod()
|
|
403
|
+
public async proveTransaction(
|
|
404
|
+
publicInput: BlockProverPublicInput,
|
|
405
|
+
stateProof: StateTransitionProof,
|
|
406
|
+
runtimeProof: DynamicRuntimeProof,
|
|
407
|
+
executionData: BlockProverExecutionData,
|
|
408
|
+
verificationKeyWitness: RuntimeVerificationKeyAttestation
|
|
409
|
+
): Promise<BlockProverPublicOutput> {
|
|
410
|
+
const state: BlockProverState = {
|
|
411
|
+
...publicInput,
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
state.networkStateHash.assertEquals(
|
|
415
|
+
executionData.networkState.hash(),
|
|
416
|
+
"ExecutionData Networkstate doesn't equal public input hash"
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
// Verify the [methodId, vk] tuple against the baked-in vk tree root
|
|
420
|
+
const { verificationKey, witness: verificationKeyTreeWitness } =
|
|
421
|
+
verificationKeyWitness;
|
|
422
|
+
|
|
423
|
+
const root = Field(this.verificationKeyService.getRoot());
|
|
424
|
+
const calculatedRoot = verificationKeyTreeWitness.calculateRoot(
|
|
425
|
+
new MethodVKConfigData({
|
|
426
|
+
methodId: executionData.transaction.methodId,
|
|
427
|
+
vkHash: verificationKey.hash,
|
|
428
|
+
}).hash()
|
|
429
|
+
);
|
|
430
|
+
root.assertEquals(calculatedRoot, errors.invalidZkProgramTreeRoot());
|
|
431
|
+
|
|
432
|
+
const bundleInclusionState = this.addTransactionToBundle(
|
|
433
|
+
state,
|
|
434
|
+
runtimeProof.publicOutput.isMessage,
|
|
435
|
+
executionData.transaction
|
|
436
|
+
);
|
|
437
|
+
|
|
438
|
+
const stateTo = await this.applyTransaction(
|
|
439
|
+
bundleInclusionState,
|
|
440
|
+
stateProof,
|
|
441
|
+
runtimeProof,
|
|
442
|
+
executionData,
|
|
443
|
+
verificationKey
|
|
444
|
+
);
|
|
445
|
+
|
|
446
|
+
return new BlockProverPublicOutput({
|
|
447
|
+
...stateTo,
|
|
448
|
+
blockNumber: maxField(),
|
|
449
|
+
closed: Bool(false),
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
private assertSTProofInput(
|
|
454
|
+
stateTransitionProof: StateTransitionProof,
|
|
455
|
+
stateRoot: Field
|
|
456
|
+
) {
|
|
457
|
+
stateTransitionProof.publicInput.stateTransitionsHash.assertEquals(
|
|
458
|
+
Field(0),
|
|
459
|
+
errors.stateProofNotStartingAtZero()
|
|
460
|
+
);
|
|
461
|
+
stateTransitionProof.publicInput.protocolTransitionsHash.assertEquals(
|
|
462
|
+
Field(0),
|
|
463
|
+
errors.stateProofNotStartingAtZero()
|
|
464
|
+
);
|
|
465
|
+
|
|
466
|
+
// Assert from state roots
|
|
467
|
+
stateRoot.assertEquals(
|
|
468
|
+
stateTransitionProof.publicInput.stateRoot,
|
|
469
|
+
errors.propertyNotMatching("from state root")
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
@provableMethod()
|
|
474
|
+
public async proveBlock(
|
|
475
|
+
publicInput: BlockProverPublicInput,
|
|
476
|
+
networkState: NetworkState,
|
|
477
|
+
blockWitness: BlockHashMerkleTreeWitness,
|
|
478
|
+
stateTransitionProof: StateTransitionProof,
|
|
479
|
+
transactionProof: BlockProverProof
|
|
480
|
+
): Promise<BlockProverPublicOutput> {
|
|
481
|
+
const state: BlockProverState = {
|
|
482
|
+
...publicInput,
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
// 1. Make assertions about the inputs
|
|
486
|
+
publicInput.transactionsHash.assertEquals(
|
|
487
|
+
Field(0),
|
|
488
|
+
"Transactionshash has to start at 0"
|
|
489
|
+
);
|
|
490
|
+
publicInput.networkStateHash.assertEquals(
|
|
491
|
+
networkState.hash(),
|
|
492
|
+
"Wrong NetworkState supplied"
|
|
493
|
+
);
|
|
494
|
+
|
|
495
|
+
transactionProof.publicInput.transactionsHash.assertEquals(
|
|
496
|
+
Field(0),
|
|
497
|
+
"TransactionProof transactionshash has to start at 0"
|
|
498
|
+
);
|
|
499
|
+
transactionProof.publicInput.blockHashRoot.assertEquals(
|
|
500
|
+
Field(0),
|
|
501
|
+
"TransactionProof cannot carry the blockHashRoot - publicInput"
|
|
502
|
+
);
|
|
503
|
+
transactionProof.publicOutput.blockHashRoot.assertEquals(
|
|
504
|
+
Field(0),
|
|
505
|
+
"TransactionProof cannot carry the blockHashRoot - publicOutput"
|
|
506
|
+
);
|
|
507
|
+
transactionProof.publicInput.networkStateHash.assertEquals(
|
|
508
|
+
transactionProof.publicOutput.networkStateHash,
|
|
509
|
+
"TransactionProof cannot alter the network state"
|
|
510
|
+
);
|
|
511
|
+
transactionProof.publicInput.eternalTransactionsHash.assertEquals(
|
|
512
|
+
state.eternalTransactionsHash,
|
|
513
|
+
"TransactionProof starting eternalTransactionHash not matching"
|
|
514
|
+
);
|
|
515
|
+
transactionProof.publicInput.incomingMessagesHash.assertEquals(
|
|
516
|
+
state.incomingMessagesHash,
|
|
517
|
+
"TransactionProof starting incomingMessagesHash not matching"
|
|
518
|
+
);
|
|
519
|
+
|
|
520
|
+
// Verify ST Proof only if STs have been emitted,
|
|
521
|
+
// otherwise we can input a dummy proof
|
|
522
|
+
const stsEmitted = stateTransitionProof.publicOutput.stateTransitionsHash
|
|
523
|
+
.equals(0)
|
|
524
|
+
.and(stateTransitionProof.publicOutput.protocolTransitionsHash.equals(0))
|
|
525
|
+
.not();
|
|
526
|
+
stateTransitionProof.verifyIf(stsEmitted);
|
|
527
|
+
|
|
528
|
+
// Verify Transaction proof if it has at least 1 tx
|
|
529
|
+
// We have to compare the whole input and output because we can make no
|
|
530
|
+
// assumptions about the values, since it can be an arbitrary dummy-proof
|
|
531
|
+
const txProofOutput = transactionProof.publicOutput;
|
|
532
|
+
const verifyTransactionProof = txProofOutput.equals(
|
|
533
|
+
transactionProof.publicInput,
|
|
534
|
+
txProofOutput.closed,
|
|
535
|
+
txProofOutput.blockNumber
|
|
536
|
+
);
|
|
537
|
+
transactionProof.verifyIf(verifyTransactionProof);
|
|
538
|
+
|
|
539
|
+
// 2. Execute beforeBlock hooks
|
|
540
|
+
const beforeBlockResult = await this.executeBlockHooks(
|
|
541
|
+
state,
|
|
542
|
+
networkState,
|
|
543
|
+
"beforeBlock"
|
|
544
|
+
);
|
|
545
|
+
|
|
546
|
+
const beforeBlockHashList = new StateTransitionReductionList(
|
|
547
|
+
ProvableStateTransition
|
|
548
|
+
);
|
|
549
|
+
beforeBlockResult.stateTransitions.forEach((st) => {
|
|
550
|
+
beforeBlockHashList.push(st.toProvable());
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
// We are reusing protocolSTs here as beforeBlock STs
|
|
554
|
+
// TODO Not possible atm bcs we can't have a seperation between protocol/runtime state roots,
|
|
555
|
+
// which we would for both before and after to be able to emit STs
|
|
556
|
+
|
|
557
|
+
// stateTransitionProof.publicInput.protocolTransitionsHash.assertEquals(
|
|
558
|
+
// beforeBlockHashList.commitment
|
|
559
|
+
// );
|
|
560
|
+
// state.stateRoot = stateTransitionProof.publicInput.protocolStateRoot;
|
|
561
|
+
|
|
562
|
+
// TODO Only for now
|
|
563
|
+
beforeBlockHashList.commitment.assertEquals(
|
|
564
|
+
Field(0),
|
|
565
|
+
"beforeBlock() cannot emit state transitions yet"
|
|
566
|
+
);
|
|
567
|
+
|
|
568
|
+
// 4. Apply TX-type BlockProof
|
|
569
|
+
transactionProof.publicInput.networkStateHash.assertEquals(
|
|
570
|
+
beforeBlockResult.networkState.hash(),
|
|
571
|
+
"TransactionProof networkstate hash not matching beforeBlock hook result"
|
|
572
|
+
);
|
|
573
|
+
transactionProof.publicInput.stateRoot.assertEquals(
|
|
574
|
+
state.stateRoot,
|
|
575
|
+
"TransactionProof input state root not matching blockprover state root"
|
|
576
|
+
);
|
|
577
|
+
|
|
578
|
+
state.stateRoot = transactionProof.publicOutput.stateRoot;
|
|
579
|
+
state.transactionsHash = transactionProof.publicOutput.transactionsHash;
|
|
580
|
+
state.eternalTransactionsHash =
|
|
581
|
+
transactionProof.publicOutput.eternalTransactionsHash;
|
|
582
|
+
state.incomingMessagesHash =
|
|
583
|
+
transactionProof.publicOutput.incomingMessagesHash;
|
|
584
|
+
|
|
585
|
+
// 5. Execute afterBlock hooks
|
|
586
|
+
this.assertSTProofInput(stateTransitionProof, state.stateRoot);
|
|
587
|
+
|
|
588
|
+
const afterBlockResult = await this.executeBlockHooks(
|
|
589
|
+
state,
|
|
590
|
+
beforeBlockResult.networkState,
|
|
591
|
+
"afterBlock"
|
|
592
|
+
);
|
|
593
|
+
|
|
594
|
+
const afterBlockHashList = new StateTransitionReductionList(
|
|
595
|
+
ProvableStateTransition
|
|
596
|
+
);
|
|
597
|
+
afterBlockResult.stateTransitions.forEach((st) => {
|
|
598
|
+
afterBlockHashList.push(st.toProvable());
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
state.networkStateHash = afterBlockResult.networkState.hash();
|
|
602
|
+
|
|
603
|
+
// We are reusing runtime STs here as afterBlock STs
|
|
604
|
+
stateTransitionProof.publicInput.stateTransitionsHash.assertEquals(
|
|
605
|
+
afterBlockHashList.commitment,
|
|
606
|
+
"STProof from-ST-hash not matching generated ST-hash from afterBlock hooks"
|
|
607
|
+
);
|
|
608
|
+
state.stateRoot = Provable.if(
|
|
609
|
+
stsEmitted,
|
|
610
|
+
stateTransitionProof.publicOutput.stateRoot,
|
|
611
|
+
state.stateRoot
|
|
612
|
+
);
|
|
613
|
+
|
|
614
|
+
// 6. Close block
|
|
615
|
+
|
|
616
|
+
// Calculate the new block index
|
|
617
|
+
const blockIndex = blockWitness.calculateIndex();
|
|
618
|
+
|
|
619
|
+
blockWitness
|
|
620
|
+
.calculateRoot(Field(0))
|
|
621
|
+
.assertEquals(
|
|
622
|
+
publicInput.blockHashRoot,
|
|
623
|
+
"Supplied block hash witness not matching state root"
|
|
624
|
+
);
|
|
625
|
+
|
|
626
|
+
state.blockHashRoot = blockWitness.calculateRoot(
|
|
627
|
+
new BlockHashTreeEntry({
|
|
628
|
+
// Mirroring UnprovenBlock.hash()
|
|
629
|
+
blockHash: Poseidon.hash([blockIndex, state.transactionsHash]),
|
|
630
|
+
closed: Bool(true),
|
|
631
|
+
}).hash()
|
|
632
|
+
);
|
|
633
|
+
|
|
634
|
+
return new BlockProverPublicOutput({
|
|
635
|
+
...state,
|
|
636
|
+
blockNumber: blockIndex,
|
|
637
|
+
closed: Bool(true),
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
@provableMethod()
|
|
642
|
+
public async merge(
|
|
643
|
+
publicInput: BlockProverPublicInput,
|
|
644
|
+
proof1: BlockProverProof,
|
|
645
|
+
proof2: BlockProverProof
|
|
646
|
+
): Promise<BlockProverPublicOutput> {
|
|
647
|
+
proof1.verify();
|
|
648
|
+
proof2.verify();
|
|
649
|
+
|
|
650
|
+
// Check state
|
|
651
|
+
publicInput.stateRoot.assertEquals(
|
|
652
|
+
proof1.publicInput.stateRoot,
|
|
653
|
+
errors.stateRootNotMatching("publicInput.from -> proof1.from")
|
|
654
|
+
);
|
|
655
|
+
proof1.publicOutput.stateRoot.assertEquals(
|
|
656
|
+
proof2.publicInput.stateRoot,
|
|
657
|
+
errors.stateRootNotMatching("proof1.to -> proof2.from")
|
|
658
|
+
);
|
|
659
|
+
|
|
660
|
+
// Check transaction list hash.
|
|
661
|
+
// Only assert them if these are tx proofs, skip for closed proofs
|
|
662
|
+
publicInput.transactionsHash
|
|
663
|
+
.equals(proof1.publicInput.transactionsHash)
|
|
664
|
+
.or(proof1.publicOutput.closed)
|
|
665
|
+
.assertTrue(
|
|
666
|
+
errors.transactionsHashNotMatching("publicInput.from -> proof1.from")
|
|
667
|
+
);
|
|
668
|
+
proof1.publicOutput.transactionsHash
|
|
669
|
+
.equals(proof2.publicInput.transactionsHash)
|
|
670
|
+
.or(proof1.publicOutput.closed)
|
|
671
|
+
.assertTrue(
|
|
672
|
+
errors.transactionsHashNotMatching("proof1.to -> proof2.from")
|
|
673
|
+
);
|
|
674
|
+
|
|
675
|
+
// Check networkhash
|
|
676
|
+
publicInput.networkStateHash.assertEquals(
|
|
677
|
+
proof1.publicInput.networkStateHash,
|
|
678
|
+
errors.networkStateHashNotMatching("publicInput.from -> proof1.from")
|
|
679
|
+
);
|
|
680
|
+
proof1.publicOutput.networkStateHash.assertEquals(
|
|
681
|
+
proof2.publicInput.networkStateHash,
|
|
682
|
+
errors.networkStateHashNotMatching("proof1.to -> proof2.from")
|
|
683
|
+
);
|
|
684
|
+
|
|
685
|
+
// Check blockHashRoot
|
|
686
|
+
publicInput.blockHashRoot.assertEquals(
|
|
687
|
+
proof1.publicInput.blockHashRoot,
|
|
688
|
+
errors.transactionsHashNotMatching("publicInput.from -> proof1.from")
|
|
689
|
+
);
|
|
690
|
+
proof1.publicOutput.blockHashRoot.assertEquals(
|
|
691
|
+
proof2.publicInput.blockHashRoot,
|
|
692
|
+
errors.transactionsHashNotMatching("proof1.to -> proof2.from")
|
|
693
|
+
);
|
|
694
|
+
|
|
695
|
+
// Check eternalTransactionsHash
|
|
696
|
+
publicInput.eternalTransactionsHash.assertEquals(
|
|
697
|
+
proof1.publicInput.eternalTransactionsHash,
|
|
698
|
+
errors.transactionsHashNotMatching("publicInput.from -> proof1.from")
|
|
699
|
+
);
|
|
700
|
+
proof1.publicOutput.eternalTransactionsHash.assertEquals(
|
|
701
|
+
proof2.publicInput.eternalTransactionsHash,
|
|
702
|
+
errors.transactionsHashNotMatching("proof1.to -> proof2.from")
|
|
703
|
+
);
|
|
704
|
+
|
|
705
|
+
// Check incomingMessagesHash
|
|
706
|
+
publicInput.incomingMessagesHash.assertEquals(
|
|
707
|
+
proof1.publicInput.incomingMessagesHash,
|
|
708
|
+
errors.propertyNotMatchingStep(
|
|
709
|
+
"IncomingMessagesHash",
|
|
710
|
+
"publicInput.from -> proof1.from"
|
|
711
|
+
)
|
|
712
|
+
);
|
|
713
|
+
proof1.publicOutput.incomingMessagesHash.assertEquals(
|
|
714
|
+
proof2.publicInput.incomingMessagesHash,
|
|
715
|
+
errors.propertyNotMatchingStep(
|
|
716
|
+
"IncomingMessagesHash",
|
|
717
|
+
"proof1.to -> proof2.from"
|
|
718
|
+
)
|
|
719
|
+
);
|
|
720
|
+
|
|
721
|
+
// Assert closed indicator matches
|
|
722
|
+
// (i.e. we can only merge TX-Type and Block-Type with each other)
|
|
723
|
+
proof1.publicOutput.closed.assertEquals(
|
|
724
|
+
proof2.publicOutput.closed,
|
|
725
|
+
"Closed indicators not matching"
|
|
726
|
+
);
|
|
727
|
+
|
|
728
|
+
// Either
|
|
729
|
+
// blockNumbers are unset and proofs are unclosed or
|
|
730
|
+
// both blocks are closed, then they have to increment or
|
|
731
|
+
// one block is closed, then height has to be the same
|
|
732
|
+
|
|
733
|
+
// Imperative algo would look like
|
|
734
|
+
// if(proof1.height == MAX && proof2.height == MAX){
|
|
735
|
+
// assert !proof1.closed && !proof2.closed;
|
|
736
|
+
// }else if(proof1.closed && proof2.closed){
|
|
737
|
+
// assert proof1.height + 1 == proof2.height
|
|
738
|
+
// // next one is omitted for now
|
|
739
|
+
// }else if(proof1.closed || proof2.closed{
|
|
740
|
+
// assert proof1.height == proof2.height
|
|
741
|
+
// }
|
|
742
|
+
|
|
743
|
+
const proof1Height = proof1.publicOutput.blockNumber;
|
|
744
|
+
const proof1Closed = proof1.publicOutput.closed;
|
|
745
|
+
const proof2Height = proof2.publicOutput.blockNumber;
|
|
746
|
+
const proof2Closed = proof2.publicOutput.closed;
|
|
747
|
+
|
|
748
|
+
const isValidTransactionMerge = proof1Height
|
|
749
|
+
.equals(maxField())
|
|
750
|
+
.and(proof2Height.equals(proof1Height))
|
|
751
|
+
.and(proof1Closed.or(proof2Closed).not());
|
|
752
|
+
|
|
753
|
+
const isValidClosedMerge = proof1Closed
|
|
754
|
+
.and(proof2Closed)
|
|
755
|
+
.and(proof1Height.add(1).equals(proof2Height));
|
|
756
|
+
|
|
757
|
+
isValidTransactionMerge
|
|
758
|
+
.or(isValidClosedMerge)
|
|
759
|
+
.assertTrue("Invalid BlockProof merge");
|
|
760
|
+
|
|
761
|
+
return new BlockProverPublicOutput({
|
|
762
|
+
stateRoot: proof2.publicOutput.stateRoot,
|
|
763
|
+
transactionsHash: proof2.publicOutput.transactionsHash,
|
|
764
|
+
networkStateHash: proof2.publicOutput.networkStateHash,
|
|
765
|
+
blockHashRoot: proof2.publicOutput.blockHashRoot,
|
|
766
|
+
eternalTransactionsHash: proof2.publicOutput.eternalTransactionsHash,
|
|
767
|
+
incomingMessagesHash: proof2.publicOutput.incomingMessagesHash,
|
|
768
|
+
// Provable.if(isValidClosedMerge, Bool(true), Bool(false));
|
|
769
|
+
closed: isValidClosedMerge,
|
|
770
|
+
blockNumber: proof2Height,
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* Creates the BlockProver ZkProgram.
|
|
776
|
+
* Recursive linking of proofs is done via the previously
|
|
777
|
+
* injected StateTransitionProver and the required AppChainProof class
|
|
778
|
+
*/
|
|
779
|
+
public zkProgramFactory(): PlainZkProgram<
|
|
780
|
+
BlockProverPublicInput,
|
|
781
|
+
BlockProverPublicOutput
|
|
782
|
+
>[] {
|
|
783
|
+
const { prover, stateTransitionProver } = this;
|
|
784
|
+
const StateTransitionProofClass = stateTransitionProver.zkProgram[0].Proof;
|
|
785
|
+
const RuntimeProofClass = DynamicRuntimeProof;
|
|
786
|
+
const proveTransaction = prover.proveTransaction.bind(prover);
|
|
787
|
+
const proveBlock = prover.proveBlock.bind(prover);
|
|
788
|
+
const merge = prover.merge.bind(prover);
|
|
789
|
+
|
|
790
|
+
const program = ZkProgram({
|
|
791
|
+
name: "BlockProver",
|
|
792
|
+
publicInput: BlockProverPublicInput,
|
|
793
|
+
publicOutput: BlockProverPublicOutput,
|
|
794
|
+
|
|
795
|
+
methods: {
|
|
796
|
+
proveTransaction: {
|
|
797
|
+
privateInputs: [
|
|
798
|
+
StateTransitionProofClass,
|
|
799
|
+
RuntimeProofClass,
|
|
800
|
+
BlockProverExecutionData,
|
|
801
|
+
RuntimeVerificationKeyAttestation,
|
|
802
|
+
],
|
|
803
|
+
|
|
804
|
+
async method(
|
|
805
|
+
publicInput: BlockProverPublicInput,
|
|
806
|
+
stateProof: StateTransitionProof,
|
|
807
|
+
appProof: DynamicRuntimeProof,
|
|
808
|
+
executionData: BlockProverExecutionData,
|
|
809
|
+
verificationKeyAttestation: RuntimeVerificationKeyAttestation
|
|
810
|
+
) {
|
|
811
|
+
return await proveTransaction(
|
|
812
|
+
publicInput,
|
|
813
|
+
stateProof,
|
|
814
|
+
appProof,
|
|
815
|
+
executionData,
|
|
816
|
+
verificationKeyAttestation
|
|
817
|
+
);
|
|
818
|
+
},
|
|
819
|
+
},
|
|
820
|
+
|
|
821
|
+
proveBlock: {
|
|
822
|
+
privateInputs: [
|
|
823
|
+
NetworkState,
|
|
824
|
+
BlockHashMerkleTreeWitness,
|
|
825
|
+
StateTransitionProofClass,
|
|
826
|
+
SelfProof<BlockProverPublicInput, BlockProverPublicOutput>,
|
|
827
|
+
],
|
|
828
|
+
async method(
|
|
829
|
+
publicInput: BlockProverPublicInput,
|
|
830
|
+
networkState: NetworkState,
|
|
831
|
+
blockWitness: BlockHashMerkleTreeWitness,
|
|
832
|
+
stateTransitionProof: StateTransitionProof,
|
|
833
|
+
transactionProof: BlockProverProof
|
|
834
|
+
) {
|
|
835
|
+
return await proveBlock(
|
|
836
|
+
publicInput,
|
|
837
|
+
networkState,
|
|
838
|
+
blockWitness,
|
|
839
|
+
stateTransitionProof,
|
|
840
|
+
transactionProof
|
|
841
|
+
);
|
|
842
|
+
},
|
|
843
|
+
},
|
|
844
|
+
|
|
845
|
+
merge: {
|
|
846
|
+
privateInputs: [
|
|
847
|
+
SelfProof<BlockProverPublicInput, BlockProverPublicOutput>,
|
|
848
|
+
SelfProof<BlockProverPublicInput, BlockProverPublicOutput>,
|
|
849
|
+
],
|
|
850
|
+
|
|
851
|
+
async method(
|
|
852
|
+
publicInput: BlockProverPublicInput,
|
|
853
|
+
proof1: BlockProverProof,
|
|
854
|
+
proof2: BlockProverProof
|
|
855
|
+
) {
|
|
856
|
+
return await merge(publicInput, proof1, proof2);
|
|
857
|
+
},
|
|
858
|
+
},
|
|
859
|
+
},
|
|
860
|
+
});
|
|
861
|
+
|
|
862
|
+
const methods = {
|
|
863
|
+
proveTransaction: program.proveTransaction,
|
|
864
|
+
merge: program.merge,
|
|
865
|
+
};
|
|
866
|
+
|
|
867
|
+
const SelfProofClass = ZkProgram.Proof(program);
|
|
868
|
+
|
|
869
|
+
return [
|
|
870
|
+
{
|
|
871
|
+
compile: program.compile.bind(program),
|
|
872
|
+
verify: program.verify.bind(program),
|
|
873
|
+
analyzeMethods: program.analyzeMethods.bind(program),
|
|
874
|
+
Proof: SelfProofClass,
|
|
875
|
+
methods,
|
|
876
|
+
},
|
|
877
|
+
];
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
/**
|
|
882
|
+
* BlockProver class, which aggregates a AppChainProof and
|
|
883
|
+
* a StateTransitionProof into a single BlockProof, that can
|
|
884
|
+
* then be merged to be committed to the base-layer contract
|
|
885
|
+
*/
|
|
886
|
+
@injectable()
|
|
887
|
+
export class BlockProver extends ProtocolModule implements BlockProvable {
|
|
888
|
+
public zkProgrammable: BlockProverProgrammable;
|
|
889
|
+
|
|
890
|
+
public constructor(
|
|
891
|
+
@inject("StateTransitionProver")
|
|
892
|
+
public readonly stateTransitionProver: WithZkProgrammable<
|
|
893
|
+
StateTransitionProverPublicInput,
|
|
894
|
+
StateTransitionProverPublicOutput
|
|
895
|
+
>,
|
|
896
|
+
@inject("Runtime")
|
|
897
|
+
public readonly runtime: WithZkProgrammable<undefined, MethodPublicOutput>,
|
|
898
|
+
@injectAll("ProvableTransactionHook")
|
|
899
|
+
transactionHooks: ProvableTransactionHook<unknown>[],
|
|
900
|
+
@injectAll("ProvableBlockHook")
|
|
901
|
+
blockHooks: ProvableBlockHook<unknown>[],
|
|
902
|
+
verificationKeyService: RuntimeVerificationKeyRootService
|
|
903
|
+
) {
|
|
904
|
+
super();
|
|
905
|
+
this.zkProgrammable = new BlockProverProgrammable(
|
|
906
|
+
this,
|
|
907
|
+
stateTransitionProver.zkProgrammable,
|
|
908
|
+
runtime.zkProgrammable,
|
|
909
|
+
transactionHooks,
|
|
910
|
+
blockHooks,
|
|
911
|
+
verificationKeyService
|
|
912
|
+
);
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
public proveTransaction(
|
|
916
|
+
publicInput: BlockProverPublicInput,
|
|
917
|
+
stateProof: StateTransitionProof,
|
|
918
|
+
appProof: DynamicRuntimeProof,
|
|
919
|
+
executionData: BlockProverExecutionData,
|
|
920
|
+
verificationKeyAttestation: RuntimeVerificationKeyAttestation
|
|
921
|
+
): Promise<BlockProverPublicOutput> {
|
|
922
|
+
return this.zkProgrammable.proveTransaction(
|
|
923
|
+
publicInput,
|
|
924
|
+
stateProof,
|
|
925
|
+
appProof,
|
|
926
|
+
executionData,
|
|
927
|
+
verificationKeyAttestation
|
|
928
|
+
);
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
public proveBlock(
|
|
932
|
+
publicInput: BlockProverPublicInput,
|
|
933
|
+
networkState: NetworkState,
|
|
934
|
+
blockWitness: BlockHashMerkleTreeWitness,
|
|
935
|
+
stateTransitionProof: StateTransitionProof,
|
|
936
|
+
transactionProof: BlockProverProof
|
|
937
|
+
): Promise<BlockProverPublicOutput> {
|
|
938
|
+
return this.zkProgrammable.proveBlock(
|
|
939
|
+
publicInput,
|
|
940
|
+
networkState,
|
|
941
|
+
blockWitness,
|
|
942
|
+
stateTransitionProof,
|
|
943
|
+
transactionProof
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
public merge(
|
|
948
|
+
publicInput: BlockProverPublicInput,
|
|
949
|
+
proof1: BlockProverProof,
|
|
950
|
+
proof2: BlockProverProof
|
|
951
|
+
): Promise<BlockProverPublicOutput> {
|
|
952
|
+
return this.zkProgrammable.merge(publicInput, proof1, proof2);
|
|
953
|
+
}
|
|
954
|
+
}
|