@proto-kit/protocol 0.1.1-develop.153
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/config/ConfigurableModule.d.ts +18 -0
- package/dist/config/ConfigurableModule.d.ts.map +1 -0
- package/dist/config/ConfigurableModule.js +20 -0
- package/dist/config/ConfigurationAggregator.d.ts +10 -0
- package/dist/config/ConfigurationAggregator.d.ts.map +1 -0
- package/dist/config/ConfigurationAggregator.js +35 -0
- package/dist/config/ConfigurationReceiver.d.ts +25 -0
- package/dist/config/ConfigurationReceiver.d.ts.map +1 -0
- package/dist/config/ConfigurationReceiver.js +36 -0
- package/dist/config/ModuleContainer.d.ts +44 -0
- package/dist/config/ModuleContainer.d.ts.map +1 -0
- package/dist/config/ModuleContainer.js +89 -0
- package/dist/config/types.d.ts +2 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/model/MethodPublicInput.d.ts +51 -0
- package/dist/model/MethodPublicInput.d.ts.map +1 -0
- package/dist/model/MethodPublicInput.js +11 -0
- package/dist/model/MethodPublicOutput.d.ts +59 -0
- package/dist/model/MethodPublicOutput.d.ts.map +1 -0
- package/dist/model/MethodPublicOutput.js +12 -0
- package/dist/model/Option.d.ts +94 -0
- package/dist/model/Option.d.ts.map +1 -0
- package/dist/model/Option.js +96 -0
- package/dist/model/Path.d.ts +31 -0
- package/dist/model/Path.d.ts.map +1 -0
- package/dist/model/Path.js +44 -0
- package/dist/model/StateTransition.d.ts +85 -0
- package/dist/model/StateTransition.d.ts.map +1 -0
- package/dist/model/StateTransition.js +58 -0
- package/dist/model/StateTransitionProvableBatch.d.ts +57 -0
- package/dist/model/StateTransitionProvableBatch.d.ts.map +1 -0
- package/dist/model/StateTransitionProvableBatch.js +21 -0
- package/dist/model/network/NetworkState.d.ts +64 -0
- package/dist/model/network/NetworkState.d.ts.map +1 -0
- package/dist/model/network/NetworkState.js +14 -0
- package/dist/model/transaction/ProtocolTransaction.d.ts +70 -0
- package/dist/model/transaction/ProtocolTransaction.d.ts.map +1 -0
- package/dist/model/transaction/ProtocolTransaction.js +18 -0
- package/dist/model/transaction/RuntimeTransaction.d.ts +55 -0
- package/dist/model/transaction/RuntimeTransaction.d.ts.map +1 -0
- package/dist/model/transaction/RuntimeTransaction.js +26 -0
- package/dist/protocol/Protocol.d.ts +37 -0
- package/dist/protocol/Protocol.d.ts.map +1 -0
- package/dist/protocol/Protocol.js +50 -0
- package/dist/protocol/ProtocolModule.d.ts +9 -0
- package/dist/protocol/ProtocolModule.d.ts.map +1 -0
- package/dist/protocol/ProtocolModule.js +10 -0
- package/dist/prover/block/BlockProvable.d.ts +149 -0
- package/dist/prover/block/BlockProvable.d.ts.map +1 -0
- package/dist/prover/block/BlockProvable.js +20 -0
- package/dist/prover/block/BlockProver.d.ts +48 -0
- package/dist/prover/block/BlockProver.d.ts.map +1 -0
- package/dist/prover/block/BlockProver.js +171 -0
- package/dist/prover/block/BlockScopedModule.d.ts +3 -0
- package/dist/prover/block/BlockScopedModule.d.ts.map +1 -0
- package/dist/prover/block/BlockScopedModule.js +6 -0
- package/dist/prover/statetransition/StateTransitionProvable.d.ts +84 -0
- package/dist/prover/statetransition/StateTransitionProvable.d.ts.map +1 -0
- package/dist/prover/statetransition/StateTransitionProvable.js +11 -0
- package/dist/prover/statetransition/StateTransitionProver.d.ts +39 -0
- package/dist/prover/statetransition/StateTransitionProver.d.ts.map +1 -0
- package/dist/prover/statetransition/StateTransitionProver.js +157 -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 +17 -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 +20 -0
- package/dist/src/model/Option.d.ts +158 -0
- package/dist/src/model/Option.d.ts.map +1 -0
- package/dist/src/model/Option.js +53 -0
- package/dist/src/model/Path.d.ts +35 -0
- package/dist/src/model/Path.d.ts.map +1 -0
- package/dist/src/model/Path.js +51 -0
- package/dist/src/model/StateTransition.d.ts +201 -0
- package/dist/src/model/StateTransition.d.ts.map +1 -0
- package/dist/src/model/StateTransition.js +43 -0
- package/dist/src/utils/PrefixedHashList.d.ts +15 -0
- package/dist/src/utils/PrefixedHashList.d.ts.map +1 -0
- package/dist/src/utils/PrefixedHashList.js +28 -0
- package/dist/src/utils/ProvableHashList.d.ts +30 -0
- package/dist/src/utils/ProvableHashList.d.ts.map +1 -0
- package/dist/src/utils/ProvableHashList.js +43 -0
- package/dist/utils/PrefixedHashList.d.ts +14 -0
- package/dist/utils/PrefixedHashList.d.ts.map +1 -0
- package/dist/utils/PrefixedHashList.js +12 -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/Utils.d.ts +17 -0
- package/dist/utils/Utils.d.ts.map +1 -0
- package/dist/utils/Utils.js +63 -0
- package/dist/utils/merkletree/InMemoryMerkleTreeStorage.d.ts +25 -0
- package/dist/utils/merkletree/InMemoryMerkleTreeStorage.d.ts.map +1 -0
- package/dist/utils/merkletree/InMemoryMerkleTreeStorage.js +72 -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/dist/utils/merkletree/MerkleTreeStore.d.ts +11 -0
- package/dist/utils/merkletree/MerkleTreeStore.d.ts.map +1 -0
- package/dist/utils/merkletree/MerkleTreeStore.js +1 -0
- package/dist/utils/merkletree/RollupMerkleTree.d.ts +130 -0
- package/dist/utils/merkletree/RollupMerkleTree.d.ts.map +1 -0
- package/dist/utils/merkletree/RollupMerkleTree.js +244 -0
- package/jest.config.cjs +1 -0
- package/package.json +35 -0
- package/src/Constants.ts +3 -0
- package/src/index.ts +23 -0
- package/src/model/MethodPublicOutput.ts +12 -0
- package/src/model/Option.test.ts +21 -0
- package/src/model/Option.ts +133 -0
- package/src/model/Path.ts +52 -0
- package/src/model/StateTransition.ts +72 -0
- package/src/model/StateTransitionProvableBatch.ts +31 -0
- package/src/model/Transaction.ts +29 -0
- package/src/model/network/NetworkState.ts +15 -0
- package/src/model/transaction/ProtocolTransaction.ts +25 -0
- package/src/model/transaction/RuntimeTransaction.ts +34 -0
- package/src/protocol/Protocol.ts +129 -0
- package/src/protocol/ProtocolModule.ts +27 -0
- package/src/prover/block/BlockProvable.ts +45 -0
- package/src/prover/block/BlockProver.ts +302 -0
- package/src/prover/statetransition/StateTransitionProvable.ts +40 -0
- package/src/prover/statetransition/StateTransitionProver.ts +270 -0
- package/src/prover/statetransition/StateTransitionWitnessProvider.ts +24 -0
- package/src/prover/statetransition/StateTransitionWitnessProviderReference.ts +17 -0
- package/src/utils/PrefixedProvableHashList.ts +21 -0
- package/src/utils/ProvableHashList.ts +50 -0
- package/src/utils/merkletree/InMemoryMerkleTreeStorage.ts +99 -0
- package/src/utils/merkletree/MerkleTreeStore.ts +15 -0
- package/src/utils/merkletree/RollupMerkleTree.ts +250 -0
- package/src/utils/merkletree/VirtualMerkleTreeStore.ts +21 -0
- package/src/utils/utils.ts +103 -0
- package/test/BlockProver.test.ts +127 -0
- package/test/Protocol.test.ts +27 -0
- package/test/StateTransition.test.ts +182 -0
- package/tsconfig.json +8 -0
- package/tsconfig.test.json +9 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
/* eslint-disable id-length */
|
|
11
|
+
/* eslint-disable line-comment-position */
|
|
12
|
+
/* eslint-disable no-inline-comments */
|
|
13
|
+
/* eslint-disable @typescript-eslint/no-magic-numbers */
|
|
14
|
+
import { Bool, Circuit, Field, Poseidon, Struct } from "snarkyjs";
|
|
15
|
+
import { notInCircuit } from "../utils";
|
|
16
|
+
// external API
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
18
|
+
export { RollupMerkleTree, RollupMerkleWitness };
|
|
19
|
+
// internal API
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
21
|
+
export { maybeSwap };
|
|
22
|
+
/**
|
|
23
|
+
* The {@link BaseMerkleWitness} class defines a circuit-compatible base class
|
|
24
|
+
* for [Merkle Witness'](https://computersciencewiki.org/index.php/Merkle_proof).
|
|
25
|
+
*/
|
|
26
|
+
class RollupMerkleWitness extends Struct({
|
|
27
|
+
path: Circuit.array(Field, 256 - 1),
|
|
28
|
+
isLeft: Circuit.array(Bool, 256 - 1),
|
|
29
|
+
}) {
|
|
30
|
+
height() {
|
|
31
|
+
return RollupMerkleWitness.height;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Calculates a root depending on the leaf value.
|
|
35
|
+
* @param leaf Value of the leaf node that belongs to this Witness.
|
|
36
|
+
* @returns The calculated root.
|
|
37
|
+
*/
|
|
38
|
+
calculateRoot(hash) {
|
|
39
|
+
const n = this.height();
|
|
40
|
+
for (let index = 1; index < n; ++index) {
|
|
41
|
+
const isLeft = this.isLeft[index - 1];
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
43
|
+
const [left, right] = maybeSwap(isLeft, hash, this.path[index - 1]);
|
|
44
|
+
hash = Poseidon.hash([left, right]);
|
|
45
|
+
}
|
|
46
|
+
return hash;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Calculates the index of the leaf node that belongs to this Witness.
|
|
50
|
+
* @returns Index of the leaf.
|
|
51
|
+
*/
|
|
52
|
+
calculateIndex() {
|
|
53
|
+
let powerOfTwo = Field(1);
|
|
54
|
+
let index = Field(0);
|
|
55
|
+
const n = this.height();
|
|
56
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
57
|
+
for (let index_ = 1; index_ < n; ++index_) {
|
|
58
|
+
index = Circuit.if(this.isLeft[index_ - 1], index, index.add(powerOfTwo));
|
|
59
|
+
powerOfTwo = powerOfTwo.mul(2);
|
|
60
|
+
}
|
|
61
|
+
return index;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
RollupMerkleWitness.height = 256;
|
|
65
|
+
/**
|
|
66
|
+
* A [Merkle Tree](https://en.wikipedia.org/wiki/Merkle_tree) is a binary tree in
|
|
67
|
+
* which every leaf is the cryptography hash of a piece of data,
|
|
68
|
+
* and every node is the hash of the concatenation of its two child nodes.
|
|
69
|
+
*
|
|
70
|
+
* A Merkle Tree allows developers to easily and securely verify
|
|
71
|
+
* the integrity of large amounts of data.
|
|
72
|
+
*
|
|
73
|
+
* Take a look at our [documentation](https://docs.minaprotocol.com/en/zkapps)
|
|
74
|
+
* on how to use Merkle Trees in combination with zkApps and
|
|
75
|
+
* zero knowledge programming!
|
|
76
|
+
*
|
|
77
|
+
* Levels are indexed from leaves (level 0) to root (level N - 1).
|
|
78
|
+
*/
|
|
79
|
+
class RollupMerkleTree {
|
|
80
|
+
static get leafCount() {
|
|
81
|
+
return 2n ** BigInt(RollupMerkleTree.height - 1);
|
|
82
|
+
}
|
|
83
|
+
constructor(store) {
|
|
84
|
+
this.store = store;
|
|
85
|
+
// eslint-disable-next-line @shopify/prefer-class-properties
|
|
86
|
+
this.zeroes = [0n];
|
|
87
|
+
for (let index = 1; index < RollupMerkleTree.height; index += 1) {
|
|
88
|
+
const previousLevel = Field(this.zeroes[index - 1]);
|
|
89
|
+
this.zeroes.push(Poseidon.hash([previousLevel, previousLevel]).toBigInt());
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Returns a node which lives at a given index and level.
|
|
94
|
+
* @param level Level of the node.
|
|
95
|
+
* @param index Index of the node.
|
|
96
|
+
* @returns The data of the node.
|
|
97
|
+
*/
|
|
98
|
+
getNode(level, index) {
|
|
99
|
+
return Field(this.store.getNode(index, level) ?? this.zeroes[level]);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Returns the root of the [Merkle Tree](https://en.wikipedia.org/wiki/Merkle_tree).
|
|
103
|
+
* @returns The root of the Merkle Tree.
|
|
104
|
+
*/
|
|
105
|
+
getRoot() {
|
|
106
|
+
return this.getNode(RollupMerkleTree.height - 1, 0n);
|
|
107
|
+
}
|
|
108
|
+
// eslint-disable-next-line no-warning-comments
|
|
109
|
+
// TODO: this allows to set a node at an index larger than the size. OK?
|
|
110
|
+
setNode(level, index, value) {
|
|
111
|
+
this.store.setNode(index, level, value.toBigInt());
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* TODO: if this is passed an index bigger than the max, it will set a couple
|
|
115
|
+
* of out-of-bounds nodes but not affect the real Merkle root. OK?
|
|
116
|
+
*/
|
|
117
|
+
/**
|
|
118
|
+
* Sets the value of a leaf node at a given index to a given value.
|
|
119
|
+
* @param index Position of the leaf node.
|
|
120
|
+
* @param leaf New value.
|
|
121
|
+
*/
|
|
122
|
+
setLeaf(index, leaf) {
|
|
123
|
+
if (index >= this.leafCount) {
|
|
124
|
+
index %= this.leafCount;
|
|
125
|
+
}
|
|
126
|
+
this.setNode(0, index, leaf);
|
|
127
|
+
let currentIndex = index;
|
|
128
|
+
for (let level = 1; level < RollupMerkleTree.height; level += 1) {
|
|
129
|
+
currentIndex /= 2n;
|
|
130
|
+
const left = this.getNode(level - 1, currentIndex * 2n);
|
|
131
|
+
const right = this.getNode(level - 1, currentIndex * 2n + 1n);
|
|
132
|
+
this.setNode(level, currentIndex, Poseidon.hash([left, right]));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Returns the witness (also known as
|
|
137
|
+
* [Merkle Proof or Merkle Witness](https://computersciencewiki.org/index.php/Merkle_proof))
|
|
138
|
+
* for the leaf at the given index.
|
|
139
|
+
* @param index Position of the leaf node.
|
|
140
|
+
* @returns The witness that belongs to the leaf.
|
|
141
|
+
*/
|
|
142
|
+
getWitness(index) {
|
|
143
|
+
if (index >= this.leafCount) {
|
|
144
|
+
index %= this.leafCount;
|
|
145
|
+
}
|
|
146
|
+
const path = [];
|
|
147
|
+
const isLefts = [];
|
|
148
|
+
for (let level = 0; level < RollupMerkleTree.height - 1; level += 1) {
|
|
149
|
+
const isLeft = index % 2n === 0n;
|
|
150
|
+
const sibling = this.getNode(level, isLeft ? index + 1n : index - 1n);
|
|
151
|
+
isLefts.push(Bool(isLeft));
|
|
152
|
+
path.push(sibling);
|
|
153
|
+
index /= 2n;
|
|
154
|
+
}
|
|
155
|
+
return new RollupMerkleWitness({
|
|
156
|
+
isLeft: isLefts,
|
|
157
|
+
path,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
// eslint-disable-next-line no-warning-comments, max-len
|
|
161
|
+
// TODO: should this take an optional offset? should it fail if the array is too long?
|
|
162
|
+
/**
|
|
163
|
+
* Fills all leaves of the tree.
|
|
164
|
+
* @param leaves Values to fill the leaves with.
|
|
165
|
+
*/
|
|
166
|
+
fill(leaves) {
|
|
167
|
+
leaves.forEach((value, index) => {
|
|
168
|
+
this.setLeaf(BigInt(index), value);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Returns the amount of leaf nodes.
|
|
173
|
+
* @returns Amount of leaf nodes.
|
|
174
|
+
*/
|
|
175
|
+
get leafCount() {
|
|
176
|
+
return RollupMerkleTree.leafCount;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
RollupMerkleTree.height = 256;
|
|
180
|
+
__decorate([
|
|
181
|
+
notInCircuit(),
|
|
182
|
+
__metadata("design:type", Function),
|
|
183
|
+
__metadata("design:paramtypes", [Number, BigInt]),
|
|
184
|
+
__metadata("design:returntype", Field)
|
|
185
|
+
], RollupMerkleTree.prototype, "getNode", null);
|
|
186
|
+
__decorate([
|
|
187
|
+
notInCircuit(),
|
|
188
|
+
__metadata("design:type", Function),
|
|
189
|
+
__metadata("design:paramtypes", []),
|
|
190
|
+
__metadata("design:returntype", Field)
|
|
191
|
+
], RollupMerkleTree.prototype, "getRoot", null);
|
|
192
|
+
__decorate([
|
|
193
|
+
notInCircuit(),
|
|
194
|
+
__metadata("design:type", Function),
|
|
195
|
+
__metadata("design:paramtypes", [BigInt, Field]),
|
|
196
|
+
__metadata("design:returntype", void 0)
|
|
197
|
+
], RollupMerkleTree.prototype, "setLeaf", null);
|
|
198
|
+
__decorate([
|
|
199
|
+
notInCircuit(),
|
|
200
|
+
__metadata("design:type", Function),
|
|
201
|
+
__metadata("design:paramtypes", [BigInt]),
|
|
202
|
+
__metadata("design:returntype", RollupMerkleWitness)
|
|
203
|
+
], RollupMerkleTree.prototype, "getWitness", null);
|
|
204
|
+
__decorate([
|
|
205
|
+
notInCircuit(),
|
|
206
|
+
__metadata("design:type", Function),
|
|
207
|
+
__metadata("design:paramtypes", [Array]),
|
|
208
|
+
__metadata("design:returntype", void 0)
|
|
209
|
+
], RollupMerkleTree.prototype, "fill", null);
|
|
210
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
211
|
+
export var MerkleTreeUtils;
|
|
212
|
+
(function (MerkleTreeUtils) {
|
|
213
|
+
function normalizeKey(key) {
|
|
214
|
+
// if(NJORD_MERKLE_TREE_HEIGHT < 256){
|
|
215
|
+
// return fieldMod(key, Field(RollupMerkleTree.leafCount).toConstant())
|
|
216
|
+
// eslint-disable-next-line max-len
|
|
217
|
+
// // return modPower2(key, RollupMerkleTree.height - 1) //TODO Fix modPower2
|
|
218
|
+
// }else{
|
|
219
|
+
return key;
|
|
220
|
+
// }
|
|
221
|
+
}
|
|
222
|
+
MerkleTreeUtils.normalizeKey = normalizeKey;
|
|
223
|
+
function checkMembership(witness, root, key, value) {
|
|
224
|
+
const root2 = witness.calculateRoot(value);
|
|
225
|
+
const key2 = witness.calculateIndex();
|
|
226
|
+
key.assertEquals(key2, "Keys of MerkleWitness does not match");
|
|
227
|
+
return root.equals(root2);
|
|
228
|
+
}
|
|
229
|
+
MerkleTreeUtils.checkMembership = checkMembership;
|
|
230
|
+
function computeRoot(witness, value) {
|
|
231
|
+
return witness.calculateRoot(value);
|
|
232
|
+
}
|
|
233
|
+
MerkleTreeUtils.computeRoot = computeRoot;
|
|
234
|
+
})(MerkleTreeUtils || (MerkleTreeUtils = {}));
|
|
235
|
+
/**
|
|
236
|
+
* More efficient version of `maybeSwapBad` which
|
|
237
|
+
* reuses an intermediate variable
|
|
238
|
+
*/
|
|
239
|
+
function maybeSwap(b, x, y) {
|
|
240
|
+
const m = b.toField().mul(x.sub(y)); // b*(x - y)
|
|
241
|
+
const x1 = y.add(m); // y + b*(x - y)
|
|
242
|
+
const y2 = x.sub(m); // x - b*(x - y) = x + b*(y - x)
|
|
243
|
+
return [x1, y2];
|
|
244
|
+
}
|
package/jest.config.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require("../../jest.config.cjs");
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@proto-kit/protocol",
|
|
3
|
+
"license": "MIT",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"version": "0.1.1-develop.153+10a7974",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc -p tsconfig.json",
|
|
9
|
+
"dev": "tsc -p tsconfig.json --watch",
|
|
10
|
+
"lint": "eslint ./src ./test",
|
|
11
|
+
"test:file": "node --experimental-vm-modules --experimental-wasm-modules --experimental-wasm-threads ../../node_modules/jest/bin/jest.js",
|
|
12
|
+
"test": "npm run test:file -- ./src/** ./test/**",
|
|
13
|
+
"test:watch": "npm run test:file -- ./src/** ./test/** --watch"
|
|
14
|
+
},
|
|
15
|
+
"main": "dist/index.js",
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@proto-kit/common": "0.1.1-develop.153+10a7974",
|
|
21
|
+
"lodash": "^4.17.21",
|
|
22
|
+
"loglevel": "^1.8.1",
|
|
23
|
+
"reflect-metadata": "^0.1.13",
|
|
24
|
+
"tsyringe": "^4.7.0"
|
|
25
|
+
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"snarkyjs": "0.11.0",
|
|
28
|
+
"tsyringe": "^4.7.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@jest/globals": "^29.5.0",
|
|
32
|
+
"@types/lodash": "^4.14.194"
|
|
33
|
+
},
|
|
34
|
+
"gitHead": "10a7974582f79be6f4f099eec83c4b0359cce2a6"
|
|
35
|
+
}
|
package/src/Constants.ts
ADDED
package/src/index.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export * from "./utils/ProvableHashList";
|
|
2
|
+
export * from "./model/StateTransition";
|
|
3
|
+
export * from "./model/StateTransitionProvableBatch";
|
|
4
|
+
export * from "./model/Option";
|
|
5
|
+
export * from "./model/Path";
|
|
6
|
+
export * from "./model/network/NetworkState";
|
|
7
|
+
export * from "./model/transaction/ProtocolTransaction";
|
|
8
|
+
export * from "./model/transaction/RuntimeTransaction";
|
|
9
|
+
export * from "./utils/PrefixedProvableHashList.js";
|
|
10
|
+
export * from "./utils/utils";
|
|
11
|
+
export * from "./prover/block/BlockProver";
|
|
12
|
+
export * from "./prover/block/BlockProvable";
|
|
13
|
+
export * from "./prover/statetransition/StateTransitionProver";
|
|
14
|
+
export * from "./prover/statetransition/StateTransitionProvable";
|
|
15
|
+
export * from "./prover/statetransition/StateTransitionWitnessProvider";
|
|
16
|
+
export * from "./utils/merkletree/MerkleTreeStore";
|
|
17
|
+
export * from "./utils/merkletree/InMemoryMerkleTreeStorage";
|
|
18
|
+
export * from "./utils/merkletree/RollupMerkleTree";
|
|
19
|
+
export * from "./model/MethodPublicOutput";
|
|
20
|
+
export * from "./prover/statetransition/StateTransitionWitnessProviderReference";
|
|
21
|
+
export * from "./protocol/Protocol";
|
|
22
|
+
export * from "./protocol/ProtocolModule";
|
|
23
|
+
export { constants as ProtocolConstants } from "./Constants";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Bool, Field, Struct } from "snarkyjs";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Public input used to link in-circuit execution with
|
|
5
|
+
* the proof's public input.
|
|
6
|
+
*/
|
|
7
|
+
export class MethodPublicOutput extends Struct({
|
|
8
|
+
stateTransitionsHash: Field,
|
|
9
|
+
status: Bool,
|
|
10
|
+
transactionHash: Field,
|
|
11
|
+
networkStateHash: Field,
|
|
12
|
+
}) {}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Bool, Field, Poseidon } from "snarkyjs";
|
|
2
|
+
|
|
3
|
+
import { Option } from "./Option";
|
|
4
|
+
|
|
5
|
+
describe("option", () => {
|
|
6
|
+
it.each([
|
|
7
|
+
[Bool(true), Field(0), Field, true],
|
|
8
|
+
[Bool(false), Field(0), Field, false],
|
|
9
|
+
])(
|
|
10
|
+
"should serialize to the correct tree value",
|
|
11
|
+
(isSome, value, valueType, shouldHash) => {
|
|
12
|
+
expect.assertions(1);
|
|
13
|
+
|
|
14
|
+
const option = Option.from(isSome, value, valueType);
|
|
15
|
+
// eslint-disable-next-line jest/no-conditional-in-test
|
|
16
|
+
const treeValue = shouldHash ? Poseidon.hash(value.toFields()) : Field(0);
|
|
17
|
+
|
|
18
|
+
expect(option.treeValue.toString()).toStrictEqual(treeValue.toString());
|
|
19
|
+
}
|
|
20
|
+
);
|
|
21
|
+
});
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Bool,
|
|
3
|
+
Field,
|
|
4
|
+
type FlexibleProvablePure,
|
|
5
|
+
Poseidon,
|
|
6
|
+
Provable,
|
|
7
|
+
Struct,
|
|
8
|
+
} from "snarkyjs";
|
|
9
|
+
|
|
10
|
+
export class ProvableOption extends Struct({
|
|
11
|
+
isSome: Bool,
|
|
12
|
+
value: Field,
|
|
13
|
+
}) {
|
|
14
|
+
public toSome() {
|
|
15
|
+
this.isSome = Bool(true);
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Option facilitating in-circuit values that may or may not exist.
|
|
22
|
+
*/
|
|
23
|
+
export class Option<Value> {
|
|
24
|
+
/**
|
|
25
|
+
* Creates a new Option from the provided parameters
|
|
26
|
+
*
|
|
27
|
+
* @param isSome
|
|
28
|
+
* @param value
|
|
29
|
+
* @param valueType
|
|
30
|
+
* @returns New option from the provided parameters.
|
|
31
|
+
*/
|
|
32
|
+
public static from<Value>(
|
|
33
|
+
isSome: Bool,
|
|
34
|
+
value: Value,
|
|
35
|
+
valueType: FlexibleProvablePure<Value>
|
|
36
|
+
) {
|
|
37
|
+
return new Option(isSome, value, valueType);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Creates a new Option from the provided parameters
|
|
42
|
+
*
|
|
43
|
+
* @param value
|
|
44
|
+
* @param valueType
|
|
45
|
+
* @returns New option from the provided parameters.
|
|
46
|
+
*/
|
|
47
|
+
public static fromValue<Value>(
|
|
48
|
+
value: Value,
|
|
49
|
+
valueType: FlexibleProvablePure<Value>
|
|
50
|
+
) {
|
|
51
|
+
return this.from(Bool(true), value, valueType);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @returns Empty / none option
|
|
56
|
+
*/
|
|
57
|
+
public static none() {
|
|
58
|
+
return new Option(Bool(false), Field(0), Field);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public static dummyValueFields<Value>(
|
|
62
|
+
valueType: FlexibleProvablePure<Value>
|
|
63
|
+
): Field[] {
|
|
64
|
+
const length = valueType.sizeInFields();
|
|
65
|
+
return Array.from({ length }, () => Field(0));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Computes a dummy value for the given value type.
|
|
70
|
+
*
|
|
71
|
+
* @param valueType - Value type to generate the dummy value for
|
|
72
|
+
* @returns Dummy value for the given value type
|
|
73
|
+
*/
|
|
74
|
+
public static dummyValue<Value>(
|
|
75
|
+
valueType: FlexibleProvablePure<Value>
|
|
76
|
+
): Value {
|
|
77
|
+
const fields = Option.dummyValueFields(valueType);
|
|
78
|
+
|
|
79
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
80
|
+
return valueType.fromFields(fields) as Value;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public isForcedSome = Bool(false);
|
|
84
|
+
|
|
85
|
+
public constructor(
|
|
86
|
+
public isSome: Bool,
|
|
87
|
+
public value: Value,
|
|
88
|
+
public valueType: FlexibleProvablePure<Value>
|
|
89
|
+
) {}
|
|
90
|
+
|
|
91
|
+
public clone() {
|
|
92
|
+
return new Option(this.isSome, this.value, this.valueType);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public forceSome() {
|
|
96
|
+
this.isForcedSome = Provable.if(this.isSome, Bool(false), Bool(true));
|
|
97
|
+
this.isSome = Bool(true);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @returns Tree representation of the current value
|
|
102
|
+
*/
|
|
103
|
+
public get treeValue() {
|
|
104
|
+
const treeValue = Poseidon.hash(this.valueType.toFields(this.value));
|
|
105
|
+
|
|
106
|
+
return Provable.if(
|
|
107
|
+
this.isSome.and(this.isForcedSome.not()),
|
|
108
|
+
treeValue,
|
|
109
|
+
Field(0)
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Returns the `to`-value as decoded as a list of fields
|
|
115
|
+
* Not in circuit
|
|
116
|
+
*/
|
|
117
|
+
public toFields(): Field[] {
|
|
118
|
+
if (this.isSome.toBoolean()) {
|
|
119
|
+
return this.valueType.toFields(this.value);
|
|
120
|
+
}
|
|
121
|
+
return [Field(0)];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @returns Provable representation of the current option.
|
|
126
|
+
*/
|
|
127
|
+
public toProvable() {
|
|
128
|
+
return new ProvableOption({
|
|
129
|
+
isSome: this.isSome,
|
|
130
|
+
value: this.treeValue,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-extraneous-class */
|
|
2
|
+
/* eslint-disable @shopify/no-fully-static-classes */
|
|
3
|
+
import { Field, type FlexibleProvablePure, Poseidon } from "snarkyjs";
|
|
4
|
+
|
|
5
|
+
import { stringToField } from "../utils/utils";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Helps manage path (key) identifiers for key-values in trees.
|
|
9
|
+
*/
|
|
10
|
+
export class Path {
|
|
11
|
+
/**
|
|
12
|
+
* Encodes a JS string as a Field
|
|
13
|
+
*
|
|
14
|
+
* @param value
|
|
15
|
+
* @returns Field representation of the provided value
|
|
16
|
+
*/
|
|
17
|
+
public static toField(value: string) {
|
|
18
|
+
return stringToField(value);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Encodes a class name and its property name into a Field
|
|
23
|
+
*
|
|
24
|
+
* @param className
|
|
25
|
+
* @param propertyKey
|
|
26
|
+
* @returns Field representation of class name + property name
|
|
27
|
+
*/
|
|
28
|
+
public static fromProperty(className: string, propertyKey: string): Field {
|
|
29
|
+
return Poseidon.hash([
|
|
30
|
+
Path.toField(className),
|
|
31
|
+
Path.toField(propertyKey),
|
|
32
|
+
Field(0),
|
|
33
|
+
]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Encodes an existing path with the provided key into a single Field.
|
|
38
|
+
*
|
|
39
|
+
* @param path
|
|
40
|
+
* @param keyType
|
|
41
|
+
* @param key
|
|
42
|
+
* @returns Field representation of the leading path + the provided key.
|
|
43
|
+
*/
|
|
44
|
+
public static fromKey<KeyType>(
|
|
45
|
+
path: Field,
|
|
46
|
+
keyType: FlexibleProvablePure<KeyType>,
|
|
47
|
+
key: KeyType
|
|
48
|
+
): Field {
|
|
49
|
+
const keyHash = Poseidon.hash(keyType.toFields(key));
|
|
50
|
+
return Poseidon.hash([path, keyHash]);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Field, Struct } from "snarkyjs";
|
|
2
|
+
|
|
3
|
+
import { Option, ProvableOption } from "./Option.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Provable representation of a State Transition, used to
|
|
7
|
+
* normalize state transitions of various value types for
|
|
8
|
+
* the state transition circuit.
|
|
9
|
+
*/
|
|
10
|
+
export class ProvableStateTransition extends Struct({
|
|
11
|
+
path: Field,
|
|
12
|
+
|
|
13
|
+
// must be applied even if `None`
|
|
14
|
+
from: ProvableOption,
|
|
15
|
+
|
|
16
|
+
// must be ignored if `None`
|
|
17
|
+
to: ProvableOption,
|
|
18
|
+
}) {
|
|
19
|
+
public static dummy(): ProvableStateTransition {
|
|
20
|
+
return new ProvableStateTransition({
|
|
21
|
+
path: Field(0),
|
|
22
|
+
from: Option.none().toProvable(),
|
|
23
|
+
to: Option.none().toProvable(),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Generic state transition that constraints the current method circuit
|
|
30
|
+
* to external state, by providing a state anchor.
|
|
31
|
+
*/
|
|
32
|
+
export class StateTransition<Value> {
|
|
33
|
+
public static from<Value>(path: Field, fromValue: Option<Value>) {
|
|
34
|
+
return new StateTransition(path, fromValue, Option.none());
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public static fromTo<Value>(
|
|
38
|
+
path: Field,
|
|
39
|
+
fromValue: Option<Value>,
|
|
40
|
+
toValue: Option<Value>
|
|
41
|
+
) {
|
|
42
|
+
return new StateTransition(path, fromValue, toValue);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public constructor(
|
|
46
|
+
public path: Field,
|
|
47
|
+
public fromValue: Option<Field> | Option<Value>,
|
|
48
|
+
public toValue: Option<Field> | Option<Value>
|
|
49
|
+
) {}
|
|
50
|
+
|
|
51
|
+
public get from() {
|
|
52
|
+
const from = this.fromValue.clone();
|
|
53
|
+
from.forceSome();
|
|
54
|
+
return from;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public get to() {
|
|
58
|
+
return this.toValue.clone();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Converts a StateTransition to a ProvableStateTransition,
|
|
63
|
+
* while enforcing the 'from' property to be 'Some' in all cases.
|
|
64
|
+
*/
|
|
65
|
+
public toProvable(): ProvableStateTransition {
|
|
66
|
+
return new ProvableStateTransition({
|
|
67
|
+
path: this.path,
|
|
68
|
+
from: this.from.toProvable(),
|
|
69
|
+
to: this.to.toProvable(),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Circuit, Struct } from "snarkyjs";
|
|
2
|
+
|
|
3
|
+
import { ProvableStateTransition } from "./StateTransition.js";
|
|
4
|
+
import { constants } from "../Constants";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A Batch of StateTransitions to be consumed by the StateTransitionProver
|
|
8
|
+
* to prove multiple STs at once
|
|
9
|
+
*/
|
|
10
|
+
export class StateTransitionProvableBatch extends Struct({
|
|
11
|
+
batch: Circuit.array(
|
|
12
|
+
ProvableStateTransition,
|
|
13
|
+
constants.stateTransitionProverBatchSize
|
|
14
|
+
),
|
|
15
|
+
}) {
|
|
16
|
+
private constructor(object: { batch: ProvableStateTransition[] }) {
|
|
17
|
+
super(object);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public static fromTransitions(
|
|
21
|
+
transitions: ProvableStateTransition[]
|
|
22
|
+
): StateTransitionProvableBatch {
|
|
23
|
+
const array = transitions.slice();
|
|
24
|
+
|
|
25
|
+
while (array.length < constants.stateTransitionProverBatchSize) {
|
|
26
|
+
array.push(ProvableStateTransition.dummy());
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return new StateTransitionProvableBatch({ batch: array });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Field,
|
|
3
|
+
FlexibleProvable,
|
|
4
|
+
Poseidon,
|
|
5
|
+
PublicKey,
|
|
6
|
+
Signature,
|
|
7
|
+
Struct,
|
|
8
|
+
UInt64,
|
|
9
|
+
} from "snarkyjs";
|
|
10
|
+
|
|
11
|
+
function argsToHash(...args: FlexibleProvable<any>[]): Field {
|
|
12
|
+
const fields = args.flatMap((argument) => argument.toFields(argument));
|
|
13
|
+
return Poseidon.hash(fields);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
class Transaction extends Struct({
|
|
17
|
+
// must be checked inside @runtimeMethod
|
|
18
|
+
methodId: Field,
|
|
19
|
+
// constructed by hashing args + appending all used proof input/output hashes at the end
|
|
20
|
+
argsHash: Field,
|
|
21
|
+
// must (due to nonce) be checked during applyTransaction
|
|
22
|
+
nonce: UInt64,
|
|
23
|
+
sender: PublicKey,
|
|
24
|
+
signature: Signature,
|
|
25
|
+
}) {
|
|
26
|
+
public toHash(): Field {
|
|
27
|
+
return Poseidon.hash(Transaction.toFields(this));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Field, Poseidon, Struct, UInt64 } from "snarkyjs";
|
|
2
|
+
|
|
3
|
+
export class CurrentBlock extends Struct({
|
|
4
|
+
height: UInt64,
|
|
5
|
+
}) {}
|
|
6
|
+
|
|
7
|
+
export class NetworkState extends Struct({
|
|
8
|
+
block: CurrentBlock,
|
|
9
|
+
}) {
|
|
10
|
+
public hash(): Field {
|
|
11
|
+
return Poseidon.hash([
|
|
12
|
+
...CurrentBlock.toFields(this.block)
|
|
13
|
+
])
|
|
14
|
+
}
|
|
15
|
+
}
|