@dorafactory/maci-sdk 0.0.6 → 0.0.7
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/index.d.ts +4 -1
- package/dist/index.js +301 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +287 -5
- package/dist/index.mjs.map +1 -1
- package/dist/libs/circom/index.d.ts +8 -1
- package/dist/libs/circom/types.d.ts +7 -0
- package/dist/libs/contract/contract.d.ts +4 -0
- package/dist/libs/indexer/indexer.d.ts +2 -2
- package/dist/libs/maci/index.d.ts +0 -0
- package/dist/libs/maci/maci.d.ts +62 -0
- package/dist/libs/maci/types.d.ts +6 -0
- package/dist/libs/query/account.d.ts +1 -1
- package/dist/libs/query/index.d.ts +1 -1
- package/dist/maci.d.ts +2 -0
- package/package.json +11 -7
- package/src/index.ts +4 -1
- package/src/libs/circom/circomlib.ts +308 -0
- package/src/libs/circom/index.ts +85 -0
- package/src/libs/circom/types.ts +8 -0
- package/src/libs/contract/contract.ts +4 -0
- package/src/libs/contract/utils.ts +2 -2
- package/src/libs/indexer/indexer.ts +3 -3
- package/src/libs/maci/index.ts +0 -0
- package/src/libs/maci/maci.ts +284 -0
- package/src/libs/maci/types.ts +6 -0
- package/src/libs/oracle-certificate/oracle-certificate.ts +1 -1
- package/src/libs/query/account.ts +1 -1
- package/src/libs/query/index.ts +1 -1
- package/src/maci.ts +3 -0
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import { OfflineSigner } from '@cosmjs/proto-signing';
|
|
2
|
+
import { SignResult, CircomParams } from './types';
|
|
3
|
+
export * from './circomlib';
|
|
1
4
|
export declare class Circom {
|
|
2
|
-
|
|
5
|
+
private network;
|
|
6
|
+
private chainId;
|
|
7
|
+
constructor({ network }: CircomParams);
|
|
8
|
+
signMessage(signer: OfflineSigner, address: string, message: string): Promise<SignResult>;
|
|
9
|
+
genKeypairFromSign(signer: OfflineSigner, address: string): Promise<import("./circomlib").Account>;
|
|
3
10
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { OfflineSigner } from '@cosmjs/proto-signing';
|
|
2
|
+
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate';
|
|
2
3
|
import { MaciClient } from './ts/Maci.client';
|
|
3
4
|
import { AMaciClient } from './ts/AMaci.client';
|
|
4
5
|
import { RegistryClient } from './ts/Registry.client';
|
|
@@ -36,4 +37,7 @@ export declare class Contract {
|
|
|
36
37
|
signer: OfflineSigner;
|
|
37
38
|
contractAddress: string;
|
|
38
39
|
}): Promise<AMaciClient>;
|
|
40
|
+
contractClient({ signer }: {
|
|
41
|
+
signer: OfflineSigner;
|
|
42
|
+
}): Promise<SigningCosmWasmClient>;
|
|
39
43
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BalanceResponse, RoundResponse, RoundsResponse, OperatorResponse, OperatorsResponse, CircuitResponse, TransactionResponse, TransactionsResponse, CircuitsResponse, ProofResponse } from '../../types';
|
|
2
2
|
import { IndexerParams } from './types';
|
|
3
3
|
import { Http } from '../http';
|
|
4
|
-
import { Round,
|
|
4
|
+
import { Round, UserAccount, Circuit, Operator, Proof, Transaction } from '../query';
|
|
5
5
|
/**
|
|
6
6
|
* @class Indexer
|
|
7
7
|
* @description This class is used to interact with Maci Indexer.
|
|
@@ -12,7 +12,7 @@ export declare class Indexer {
|
|
|
12
12
|
registryAddress: string;
|
|
13
13
|
http: Http;
|
|
14
14
|
round: Round;
|
|
15
|
-
account:
|
|
15
|
+
account: UserAccount;
|
|
16
16
|
circuit: Circuit;
|
|
17
17
|
operator: Operator;
|
|
18
18
|
proof: Proof;
|
|
File without changes
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { OfflineSigner } from '@cosmjs/proto-signing';
|
|
2
|
+
import { Circom, PublicKey } from '../circom';
|
|
3
|
+
import { Contract } from '../contract';
|
|
4
|
+
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate';
|
|
5
|
+
export declare class MACI {
|
|
6
|
+
circom: Circom;
|
|
7
|
+
contract: Contract;
|
|
8
|
+
constructor({ circom, contract }: {
|
|
9
|
+
circom: Circom;
|
|
10
|
+
contract: Contract;
|
|
11
|
+
});
|
|
12
|
+
signup({ signer, address, contractAddress, oracleCertificate, gasStation, }: {
|
|
13
|
+
signer: OfflineSigner;
|
|
14
|
+
address: string;
|
|
15
|
+
contractAddress: string;
|
|
16
|
+
oracleCertificate?: {
|
|
17
|
+
amount: string;
|
|
18
|
+
signature: string;
|
|
19
|
+
};
|
|
20
|
+
gasStation?: boolean;
|
|
21
|
+
}): Promise<void>;
|
|
22
|
+
submit: ({ signer, address, stateIdx, contractAddress, selectedOptions, operatorCoordPubKey, gasStation, }: {
|
|
23
|
+
signer: OfflineSigner;
|
|
24
|
+
address: string;
|
|
25
|
+
stateIdx: number;
|
|
26
|
+
contractAddress: string;
|
|
27
|
+
selectedOptions: {
|
|
28
|
+
idx: number;
|
|
29
|
+
vc: number;
|
|
30
|
+
}[];
|
|
31
|
+
operatorCoordPubKey: PublicKey;
|
|
32
|
+
gasStation?: boolean;
|
|
33
|
+
}) => Promise<void>;
|
|
34
|
+
submitPlan({ client, address, payload, contractAddress, gasStation, }: {
|
|
35
|
+
client: SigningCosmWasmClient;
|
|
36
|
+
address: string;
|
|
37
|
+
payload: {
|
|
38
|
+
msg: bigint[];
|
|
39
|
+
encPubkeys: PublicKey;
|
|
40
|
+
}[];
|
|
41
|
+
contractAddress: string;
|
|
42
|
+
gasStation: boolean;
|
|
43
|
+
}): Promise<import("@cosmjs/cosmwasm-stargate").DeliverTxResponse>;
|
|
44
|
+
signupSimple({ client, address, pubKey, contractAddress, gasStation, }: {
|
|
45
|
+
client: SigningCosmWasmClient;
|
|
46
|
+
address: string;
|
|
47
|
+
pubKey: PublicKey;
|
|
48
|
+
contractAddress: string;
|
|
49
|
+
gasStation?: boolean;
|
|
50
|
+
}): Promise<import("@cosmjs/cosmwasm-stargate").ExecuteResult>;
|
|
51
|
+
signupOracle({ client, address, pubKey, contractAddress, oracleCertificate, gasStation, }: {
|
|
52
|
+
client: SigningCosmWasmClient;
|
|
53
|
+
address: string;
|
|
54
|
+
pubKey: PublicKey;
|
|
55
|
+
contractAddress: string;
|
|
56
|
+
oracleCertificate: {
|
|
57
|
+
amount: string;
|
|
58
|
+
signature: string;
|
|
59
|
+
};
|
|
60
|
+
gasStation?: boolean;
|
|
61
|
+
}): Promise<import("@cosmjs/cosmwasm-stargate").ExecuteResult>;
|
|
62
|
+
}
|
package/dist/maci.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { BalanceResponse, ClientParams, RoundResponse, RoundsResponse, OperatorR
|
|
|
2
2
|
import { Http, Indexer, Contract } from './libs';
|
|
3
3
|
import { CreateAMaciRoundParams, CreateMaciRoundParams, CreateOracleMaciRoundParams } from './libs/contract/types';
|
|
4
4
|
import { OfflineSigner } from '@cosmjs/proto-signing';
|
|
5
|
+
import { Circom } from './libs/circom';
|
|
5
6
|
/**
|
|
6
7
|
* @class MaciClient
|
|
7
8
|
* @description This class is used to interact with Maci Client.
|
|
@@ -16,6 +17,7 @@ export declare class MaciClient {
|
|
|
16
17
|
http: Http;
|
|
17
18
|
indexer: Indexer;
|
|
18
19
|
contract: Contract;
|
|
20
|
+
circom: Circom;
|
|
19
21
|
feegrantOperator: string;
|
|
20
22
|
whitelistBackendPubkey: string;
|
|
21
23
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dorafactory/maci-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "SDK for interacting with maci",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"maci",
|
|
@@ -34,19 +34,23 @@
|
|
|
34
34
|
"@cosmjs/launchpad": "^0.27.1",
|
|
35
35
|
"@cosmjs/proto-signing": "^0.32.1",
|
|
36
36
|
"@cosmjs/stargate": "^0.32.1",
|
|
37
|
-
"ethers": "^6.13.4",
|
|
38
37
|
"assert": "^2.1.0",
|
|
39
38
|
"bech32": "1.1.4",
|
|
40
|
-
"
|
|
41
|
-
"ts-retry-promise": "^0.7.1",
|
|
42
|
-
"tweetnacl": "^1.0.3",
|
|
39
|
+
"@dorafactory/circomlib": "^0.0.2",
|
|
43
40
|
"colorts": "^0.1.63",
|
|
41
|
+
"cosmjs-types": "^0.9.0",
|
|
42
|
+
"blake-hash": "^2.0.0",
|
|
43
|
+
"ffjavascript": "^0.2.60",
|
|
44
|
+
"ethers": "^6.13.4",
|
|
45
|
+
"gql.tada": "^1.7.0",
|
|
46
|
+
"graphql": "^16.8.1",
|
|
44
47
|
"husky": "^8.0.3",
|
|
45
48
|
"keccak256": "^1.0.6",
|
|
46
49
|
"process": "^0.11.10",
|
|
47
|
-
"
|
|
48
|
-
"graphql": "^16.8.1",
|
|
50
|
+
"superstruct": "^1.0.3",
|
|
49
51
|
"tmp": "^0.2.1",
|
|
52
|
+
"ts-retry-promise": "^0.7.1",
|
|
53
|
+
"tweetnacl": "^1.0.3",
|
|
50
54
|
"valibot": "0.36.0"
|
|
51
55
|
},
|
|
52
56
|
"devDependencies": {
|
package/src/index.ts
CHANGED
|
@@ -5,9 +5,12 @@ export * from './libs/const';
|
|
|
5
5
|
export { MaciClient } from './maci';
|
|
6
6
|
export { Http } from './libs/http';
|
|
7
7
|
export { Round } from './libs/query';
|
|
8
|
-
export {
|
|
8
|
+
export { UserAccount } from './libs/query';
|
|
9
9
|
export { Circuit } from './libs/query';
|
|
10
10
|
export { Operator } from './libs/query';
|
|
11
11
|
export { Proof } from './libs/query';
|
|
12
12
|
export { Transaction } from './libs/query';
|
|
13
|
+
export * from './libs/circom';
|
|
13
14
|
export * from './utils';
|
|
15
|
+
export { Scalar, utils } from 'ffjavascript';
|
|
16
|
+
export { default as createBlakeHash } from 'blake-hash';
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { randomBytes } from 'crypto';
|
|
2
|
+
import {
|
|
3
|
+
babyJub,
|
|
4
|
+
eddsa,
|
|
5
|
+
poseidon,
|
|
6
|
+
poseidonEncrypt,
|
|
7
|
+
Tree,
|
|
8
|
+
} from '@dorafactory/circomlib';
|
|
9
|
+
import { Scalar, utils } from 'ffjavascript';
|
|
10
|
+
import createBlakeHash from 'blake-hash';
|
|
11
|
+
import { solidityPackedSha256 } from 'ethers';
|
|
12
|
+
|
|
13
|
+
type MixedData<T> = T | Array<MixedData<T>> | { [key: string]: MixedData<T> };
|
|
14
|
+
|
|
15
|
+
export type PrivateKey = bigint;
|
|
16
|
+
export type PublicKey = [bigint, bigint];
|
|
17
|
+
|
|
18
|
+
export interface Account {
|
|
19
|
+
privKey: PrivateKey;
|
|
20
|
+
pubKey: PublicKey;
|
|
21
|
+
formatedPrivKey: PrivateKey;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const SNARK_FIELD_SIZE =
|
|
25
|
+
21888242871839275222246405745257275088548364400416034343698204186575808495617n;
|
|
26
|
+
|
|
27
|
+
const bigInt2Buffer = (i: bigint) => {
|
|
28
|
+
let hex = i.toString(16);
|
|
29
|
+
if (hex.length % 2 === 1) {
|
|
30
|
+
hex = '0' + hex;
|
|
31
|
+
}
|
|
32
|
+
return Buffer.from(hex, 'hex');
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const genRandomKey = () => {
|
|
36
|
+
// Prevent modulo bias
|
|
37
|
+
// const lim = BigInt('0x10000000000000000000000000000000000000000000000000000000000000000')
|
|
38
|
+
// const min = (lim - SNARK_FIELD_SIZE) % SNARK_FIELD_SIZE
|
|
39
|
+
const min =
|
|
40
|
+
6350874878119819312338956282401532410528162663560392320966563075034087161851n;
|
|
41
|
+
|
|
42
|
+
let rand;
|
|
43
|
+
while (true) {
|
|
44
|
+
rand = BigInt('0x' + randomBytes(32).toString('hex'));
|
|
45
|
+
|
|
46
|
+
if (rand >= min) {
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const privKey = rand % SNARK_FIELD_SIZE;
|
|
52
|
+
return privKey;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const genPubKey = (privKey: bigint) => {
|
|
56
|
+
return eddsa.prv2pub(bigInt2Buffer(privKey));
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const stringizing = (
|
|
60
|
+
o: MixedData<bigint>,
|
|
61
|
+
path: MixedData<bigint>[] = []
|
|
62
|
+
): MixedData<string> => {
|
|
63
|
+
if (path.includes(o)) {
|
|
64
|
+
throw new Error('loop nesting!');
|
|
65
|
+
}
|
|
66
|
+
const newPath = [...path, o];
|
|
67
|
+
|
|
68
|
+
if (Array.isArray(o)) {
|
|
69
|
+
return o.map((item) => stringizing(item, newPath));
|
|
70
|
+
} else if (typeof o === 'object') {
|
|
71
|
+
const output: { [key: string]: MixedData<string> } = {};
|
|
72
|
+
for (const key in o) {
|
|
73
|
+
output[key] = stringizing(o[key], newPath);
|
|
74
|
+
}
|
|
75
|
+
return output;
|
|
76
|
+
} else {
|
|
77
|
+
return o.toString();
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const genKeypair = (pkey?: PrivateKey): Account => {
|
|
82
|
+
const privKey = pkey ? pkey % SNARK_FIELD_SIZE : genRandomKey();
|
|
83
|
+
const pubKey = genPubKey(privKey);
|
|
84
|
+
const formatedPrivKey = formatPrivKeyForBabyJub(privKey);
|
|
85
|
+
|
|
86
|
+
return { privKey, pubKey, formatedPrivKey };
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const formatPrivKeyForBabyJub = (privKey: PrivateKey) => {
|
|
90
|
+
const sBuff = eddsa.pruneBuffer(
|
|
91
|
+
createBlakeHash('blake512')
|
|
92
|
+
.update(bigInt2Buffer(privKey))
|
|
93
|
+
.digest()
|
|
94
|
+
.slice(0, 32)
|
|
95
|
+
);
|
|
96
|
+
const s = utils.leBuff2int(sBuff);
|
|
97
|
+
return Scalar.shr(s, 3);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const genEcdhSharedKey = (
|
|
101
|
+
privKey: PrivateKey,
|
|
102
|
+
pubKey: PublicKey
|
|
103
|
+
): PublicKey => {
|
|
104
|
+
const sharedKey = babyJub.mulPointEscalar(
|
|
105
|
+
pubKey,
|
|
106
|
+
formatPrivKeyForBabyJub(privKey)
|
|
107
|
+
);
|
|
108
|
+
if (sharedKey[0] === 0n) {
|
|
109
|
+
return [0n, 1n];
|
|
110
|
+
} else {
|
|
111
|
+
return sharedKey;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const genMessageFactory =
|
|
116
|
+
(
|
|
117
|
+
stateIdx: number,
|
|
118
|
+
signPriKey: PrivateKey,
|
|
119
|
+
signPubKey: PublicKey,
|
|
120
|
+
coordPubKey: PublicKey
|
|
121
|
+
) =>
|
|
122
|
+
(
|
|
123
|
+
encPriKey: PrivateKey,
|
|
124
|
+
nonce: number,
|
|
125
|
+
voIdx: number,
|
|
126
|
+
newVotes: number,
|
|
127
|
+
isLastCmd: boolean,
|
|
128
|
+
salt?: bigint
|
|
129
|
+
): bigint[] => {
|
|
130
|
+
if (!salt) {
|
|
131
|
+
// uint56
|
|
132
|
+
salt = BigInt('0x' + randomBytes(7).toString('hex'));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const packaged =
|
|
136
|
+
BigInt(nonce) +
|
|
137
|
+
(BigInt(stateIdx) << 32n) +
|
|
138
|
+
(BigInt(voIdx) << 64n) +
|
|
139
|
+
(BigInt(newVotes) << 96n) +
|
|
140
|
+
(BigInt(salt) << 192n);
|
|
141
|
+
|
|
142
|
+
let newPubKey = [...signPubKey];
|
|
143
|
+
if (isLastCmd) {
|
|
144
|
+
newPubKey = [0n, 0n];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const hash = poseidon([packaged, ...newPubKey]);
|
|
148
|
+
const signature = eddsa.signPoseidon(bigInt2Buffer(signPriKey), hash);
|
|
149
|
+
|
|
150
|
+
const command = [packaged, ...newPubKey, ...signature.R8, signature.S];
|
|
151
|
+
|
|
152
|
+
const message = poseidonEncrypt(
|
|
153
|
+
command,
|
|
154
|
+
genEcdhSharedKey(encPriKey, coordPubKey),
|
|
155
|
+
0n
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
return message;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// Batch generate encrypted commands.
|
|
162
|
+
// output format just like (with commands 1 ~ N):
|
|
163
|
+
// [
|
|
164
|
+
// [msg_N, msg_N-1, ... msg_3, msg_2, msg_1],
|
|
165
|
+
// [pubkey_N, pubkey_N-1, ... pubkey_3, pubkey_2, pubkey_1]
|
|
166
|
+
// ]
|
|
167
|
+
// and change the public key at command_N
|
|
168
|
+
export const batchGenMessage = (
|
|
169
|
+
stateIdx: number,
|
|
170
|
+
account: Account,
|
|
171
|
+
coordPubKey: PublicKey,
|
|
172
|
+
plan: [number, number][]
|
|
173
|
+
) => {
|
|
174
|
+
const genMessage = genMessageFactory(
|
|
175
|
+
stateIdx,
|
|
176
|
+
account.privKey,
|
|
177
|
+
account.pubKey,
|
|
178
|
+
coordPubKey
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
const payload = [];
|
|
182
|
+
for (let i = plan.length - 1; i >= 0; i--) {
|
|
183
|
+
const p = plan[i];
|
|
184
|
+
const encAccount = genKeypair();
|
|
185
|
+
const msg = genMessage(
|
|
186
|
+
encAccount.privKey,
|
|
187
|
+
i + 1,
|
|
188
|
+
p[0],
|
|
189
|
+
p[1],
|
|
190
|
+
i === plan.length - 1
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
payload.push({
|
|
194
|
+
msg,
|
|
195
|
+
encPubkeys: encAccount.pubKey,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return payload;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
export const privateKeyFromTxt = (txt: string) => {
|
|
203
|
+
if (typeof txt !== 'string') {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const key = txt.split('\n')[1] || '';
|
|
207
|
+
if (key.length !== 512) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const keys = key.match(/[0-9a-f]{128}/g);
|
|
211
|
+
if (!keys || keys.length !== 4) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const priKey = poseidon(keys.map((k) => BigInt('0x' + k)));
|
|
215
|
+
return genKeypair(priKey % SNARK_FIELD_SIZE);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const rerandomize = (
|
|
219
|
+
pubKey: bigint[],
|
|
220
|
+
ciphertext: { c1: bigint[]; c2: bigint[] },
|
|
221
|
+
randomVal = genRandomKey()
|
|
222
|
+
) => {
|
|
223
|
+
const d1 = babyJub.addPoint(
|
|
224
|
+
babyJub.mulPointEscalar(babyJub.Base8, randomVal),
|
|
225
|
+
ciphertext.c1
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
const d2 = babyJub.addPoint(
|
|
229
|
+
babyJub.mulPointEscalar(pubKey, randomVal),
|
|
230
|
+
ciphertext.c2
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
d1,
|
|
235
|
+
d2,
|
|
236
|
+
} as { d1: bigint[]; d2: bigint[] };
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
export const genAddKeyProof = async (
|
|
240
|
+
depth: number,
|
|
241
|
+
{
|
|
242
|
+
coordPubKey,
|
|
243
|
+
oldKey,
|
|
244
|
+
deactivates,
|
|
245
|
+
}: {
|
|
246
|
+
coordPubKey: PublicKey;
|
|
247
|
+
oldKey: Account;
|
|
248
|
+
deactivates: bigint[][];
|
|
249
|
+
}
|
|
250
|
+
) => {
|
|
251
|
+
const sharedKeyHash = poseidon(genEcdhSharedKey(oldKey.privKey, coordPubKey));
|
|
252
|
+
|
|
253
|
+
const randomVal = genRandomKey();
|
|
254
|
+
const deactivateIdx = deactivates.findIndex((d) => d[4] === sharedKeyHash);
|
|
255
|
+
if (deactivateIdx < 0) {
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const deactivateLeaf = deactivates[deactivateIdx];
|
|
260
|
+
|
|
261
|
+
const c1 = [deactivateLeaf[0], deactivateLeaf[1]];
|
|
262
|
+
const c2 = [deactivateLeaf[2], deactivateLeaf[3]];
|
|
263
|
+
|
|
264
|
+
const { d1, d2 } = rerandomize(coordPubKey, { c1, c2 }, randomVal);
|
|
265
|
+
|
|
266
|
+
const nullifier = poseidon([oldKey.formatedPrivKey, 1444992409218394441042n]);
|
|
267
|
+
|
|
268
|
+
const tree = new Tree(5, depth, 0n);
|
|
269
|
+
const leaves = deactivates.map((d) => poseidon(d));
|
|
270
|
+
tree.initLeaves(leaves);
|
|
271
|
+
|
|
272
|
+
const deactivateRoot = tree.root;
|
|
273
|
+
const deactivateLeafPathElements = tree.pathElementOf(deactivateIdx);
|
|
274
|
+
|
|
275
|
+
const inputHash =
|
|
276
|
+
BigInt(
|
|
277
|
+
solidityPackedSha256(
|
|
278
|
+
new Array(7).fill('uint256'),
|
|
279
|
+
stringizing([
|
|
280
|
+
deactivateRoot,
|
|
281
|
+
poseidon(coordPubKey),
|
|
282
|
+
nullifier,
|
|
283
|
+
d1[0],
|
|
284
|
+
d1[1],
|
|
285
|
+
d2[0],
|
|
286
|
+
d2[1],
|
|
287
|
+
]) as string[]
|
|
288
|
+
)
|
|
289
|
+
) % SNARK_FIELD_SIZE;
|
|
290
|
+
|
|
291
|
+
const input = {
|
|
292
|
+
inputHash,
|
|
293
|
+
coordPubKey,
|
|
294
|
+
deactivateRoot,
|
|
295
|
+
deactivateIndex: deactivateIdx,
|
|
296
|
+
deactivateLeaf: poseidon(deactivateLeaf),
|
|
297
|
+
c1,
|
|
298
|
+
c2,
|
|
299
|
+
randomVal,
|
|
300
|
+
d1,
|
|
301
|
+
d2,
|
|
302
|
+
deactivateLeafPathElements,
|
|
303
|
+
nullifier,
|
|
304
|
+
oldPrivateKey: oldKey.formatedPrivKey,
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
return input;
|
|
308
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OfflineSigner,
|
|
3
|
+
OfflineDirectSigner,
|
|
4
|
+
isOfflineDirectSigner,
|
|
5
|
+
} from '@cosmjs/proto-signing';
|
|
6
|
+
import { StdSignDoc } from '@cosmjs/amino';
|
|
7
|
+
import { SignDoc } from 'cosmjs-types/cosmos/tx/v1beta1/tx';
|
|
8
|
+
import { getDefaultParams } from '../const';
|
|
9
|
+
import { PublicKey, genKeypair, stringizing } from './circomlib';
|
|
10
|
+
import { SignResult, CircomParams } from './types';
|
|
11
|
+
export * from './circomlib';
|
|
12
|
+
|
|
13
|
+
export class Circom {
|
|
14
|
+
private network: string;
|
|
15
|
+
private chainId: string;
|
|
16
|
+
|
|
17
|
+
constructor({ network }: CircomParams) {
|
|
18
|
+
this.network = network;
|
|
19
|
+
this.chainId = getDefaultParams(network).chainId;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async signMessage(
|
|
23
|
+
signer: OfflineSigner,
|
|
24
|
+
address: string,
|
|
25
|
+
message: string
|
|
26
|
+
): Promise<SignResult> {
|
|
27
|
+
const accounts = await signer.getAccounts();
|
|
28
|
+
const account = accounts.find((acc) => acc.address === address);
|
|
29
|
+
|
|
30
|
+
if (!account) {
|
|
31
|
+
throw new Error(`Address ${address} not found in wallet`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (isOfflineDirectSigner(signer)) {
|
|
35
|
+
// Direct
|
|
36
|
+
const signDoc: SignDoc = {
|
|
37
|
+
bodyBytes: new TextEncoder().encode(message),
|
|
38
|
+
authInfoBytes: new Uint8Array(),
|
|
39
|
+
chainId: this.chainId,
|
|
40
|
+
accountNumber: BigInt(0),
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const { signature } = await signer.signDirect(address, signDoc);
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
signature: signature.signature,
|
|
47
|
+
pubkey: account.pubkey,
|
|
48
|
+
};
|
|
49
|
+
} else {
|
|
50
|
+
// Amino
|
|
51
|
+
const signDoc: StdSignDoc = {
|
|
52
|
+
chain_id: this.chainId,
|
|
53
|
+
account_number: '0',
|
|
54
|
+
sequence: '0',
|
|
55
|
+
fee: {
|
|
56
|
+
gas: '0',
|
|
57
|
+
amount: [],
|
|
58
|
+
},
|
|
59
|
+
msgs: [],
|
|
60
|
+
memo: message,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const { signature } = await signer.signAmino(address, signDoc);
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
signature: signature.signature,
|
|
67
|
+
pubkey: account.pubkey,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async genKeypairFromSign(signer: OfflineSigner, address: string) {
|
|
73
|
+
const sig = await this.signMessage(
|
|
74
|
+
signer,
|
|
75
|
+
address,
|
|
76
|
+
'Generate_MACI_Private_Key'
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const sign = BigInt(
|
|
80
|
+
'0x' + Buffer.from(sig.signature, 'base64').toString('hex')
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
return genKeypair(sign);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -150,8 +150,8 @@ export function getContractParams(
|
|
|
150
150
|
case MaciRoundType.ORACLE_MACI:
|
|
151
151
|
return {
|
|
152
152
|
parameters: CIRCUIT_INFO['9-4-3-625'].parameter,
|
|
153
|
-
groth16ProcessVkey
|
|
154
|
-
groth16TallyVkey
|
|
153
|
+
groth16ProcessVkey,
|
|
154
|
+
groth16TallyVkey,
|
|
155
155
|
plonkProcessVkey: null,
|
|
156
156
|
plonkTallyVkey: null,
|
|
157
157
|
maciVoteType,
|
|
@@ -14,7 +14,7 @@ import { IndexerParams } from './types';
|
|
|
14
14
|
import { Http } from '../http';
|
|
15
15
|
import {
|
|
16
16
|
Round,
|
|
17
|
-
|
|
17
|
+
UserAccount,
|
|
18
18
|
Circuit,
|
|
19
19
|
Operator,
|
|
20
20
|
Proof,
|
|
@@ -32,7 +32,7 @@ export class Indexer {
|
|
|
32
32
|
|
|
33
33
|
public http: Http;
|
|
34
34
|
public round: Round;
|
|
35
|
-
public account:
|
|
35
|
+
public account: UserAccount;
|
|
36
36
|
public circuit: Circuit;
|
|
37
37
|
public operator: Operator;
|
|
38
38
|
public proof: Proof;
|
|
@@ -55,7 +55,7 @@ export class Indexer {
|
|
|
55
55
|
this.registryAddress = registryAddress;
|
|
56
56
|
|
|
57
57
|
this.round = new Round(this.http);
|
|
58
|
-
this.account = new
|
|
58
|
+
this.account = new UserAccount(this.http);
|
|
59
59
|
this.circuit = new Circuit(this.http);
|
|
60
60
|
this.operator = new Operator(this.http, this.registryAddress);
|
|
61
61
|
this.proof = new Proof(this.http);
|
|
File without changes
|