@waku/rln 0.1.8-e224c05.0 → 0.1.8-e800af3.0
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/bundle/_virtual/utils.js +2 -2
- package/bundle/_virtual/utils2.js +2 -2
- package/bundle/index.js +6 -1
- package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/_sha2.js +1 -1
- package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/hmac.js +1 -1
- package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/pbkdf2.js +1 -1
- package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/scrypt.js +1 -1
- package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/sha256.js +1 -1
- package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/sha512.js +1 -1
- package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/utils.js +1 -1
- package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/random.js +1 -1
- package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/utils.js +2 -2
- package/bundle/node_modules/@chainsafe/is-ip/lib/is-ip.js +12 -0
- package/bundle/node_modules/@chainsafe/is-ip/lib/parse.js +26 -0
- package/bundle/node_modules/@chainsafe/is-ip/lib/parser.js +202 -0
- package/bundle/node_modules/@multiformats/multiaddr/dist/src/constants.js +43 -0
- package/bundle/node_modules/@multiformats/multiaddr/dist/src/errors.js +17 -0
- package/bundle/node_modules/@multiformats/multiaddr/dist/src/registry.js +245 -0
- package/bundle/node_modules/@multiformats/multiaddr/dist/src/utils.js +191 -0
- package/bundle/node_modules/@multiformats/multiaddr/dist/src/validation.js +30 -0
- package/bundle/node_modules/@noble/hashes/esm/hmac.js +88 -0
- package/bundle/node_modules/@noble/hashes/esm/sha3.js +1 -1
- package/bundle/node_modules/@noble/hashes/esm/utils.js +8 -1
- package/bundle/node_modules/@waku/zerokit-rln-wasm/rln_wasm.js +517 -255
- package/bundle/node_modules/it-length-prefixed/dist/src/decode.js +6 -0
- package/bundle/node_modules/multiformats/dist/src/bases/base10.js +3 -1
- package/bundle/node_modules/multiformats/dist/src/bases/base16.js +4 -2
- package/bundle/node_modules/multiformats/dist/src/bases/base2.js +3 -1
- package/bundle/node_modules/multiformats/dist/src/bases/base256emoji.js +3 -1
- package/bundle/node_modules/multiformats/dist/src/bases/base32.js +11 -9
- package/bundle/node_modules/multiformats/dist/src/bases/base36.js +4 -2
- package/bundle/node_modules/multiformats/dist/src/bases/base58.js +4 -2
- package/bundle/node_modules/multiformats/dist/src/bases/base64.js +6 -4
- package/bundle/node_modules/multiformats/dist/src/bases/base8.js +3 -1
- package/bundle/node_modules/multiformats/dist/src/bases/identity.js +3 -1
- package/bundle/node_modules/multiformats/dist/src/basics.js +15 -0
- package/bundle/node_modules/multiformats/dist/src/bytes.js +15 -1
- package/bundle/node_modules/multiformats/dist/src/cid.js +371 -0
- package/bundle/node_modules/multiformats/dist/src/hashes/digest.js +62 -0
- package/bundle/node_modules/multiformats/dist/src/varint.js +15 -0
- package/bundle/node_modules/multiformats/dist/src/vendor/varint.js +78 -0
- package/bundle/node_modules/protons-runtime/dist/src/codec.js +20 -0
- package/bundle/node_modules/protons-runtime/dist/src/codecs/enum.js +24 -0
- package/bundle/node_modules/protons-runtime/dist/src/codecs/message.js +7 -0
- package/bundle/node_modules/protons-runtime/dist/src/decode.js +8 -0
- package/bundle/node_modules/protons-runtime/dist/src/encode.js +11 -0
- package/bundle/node_modules/protons-runtime/dist/src/index.js +30 -0
- package/bundle/node_modules/protons-runtime/dist/src/utils/float.js +54 -0
- package/bundle/node_modules/protons-runtime/dist/src/utils/longbits.js +175 -0
- package/bundle/node_modules/protons-runtime/dist/src/utils/pool.js +28 -0
- package/bundle/node_modules/protons-runtime/dist/src/utils/reader.js +367 -0
- package/bundle/node_modules/protons-runtime/dist/src/utils/utf8.js +99 -0
- package/bundle/node_modules/protons-runtime/dist/src/utils/writer.js +438 -0
- package/bundle/node_modules/uint8-varint/dist/src/index.js +124 -0
- package/bundle/node_modules/uint8arrays/dist/src/alloc.js +17 -0
- package/bundle/node_modules/uint8arrays/dist/src/concat.js +20 -0
- package/bundle/node_modules/uint8arrays/dist/src/from-string.js +19 -0
- package/bundle/node_modules/uint8arrays/dist/src/to-string.js +19 -0
- package/bundle/node_modules/uint8arrays/dist/src/util/as-uint8array.js +9 -0
- package/bundle/node_modules/uint8arrays/dist/src/util/bases.js +49 -0
- package/bundle/packages/core/dist/lib/connection_manager/connection_limiter.js +18 -0
- package/bundle/packages/core/dist/lib/connection_manager/connection_manager.js +24 -0
- package/bundle/packages/core/dist/lib/connection_manager/dialer.js +14 -0
- package/bundle/packages/core/dist/lib/connection_manager/discovery_dialer.js +14 -0
- package/bundle/packages/core/dist/lib/connection_manager/keep_alive_manager.js +15 -0
- package/bundle/packages/core/dist/lib/connection_manager/shard_reader.js +14 -0
- package/bundle/packages/core/dist/lib/filter/filter.js +28 -0
- package/bundle/packages/core/dist/lib/light_push/light_push.js +28 -0
- package/bundle/packages/core/dist/lib/message/version_0.js +172 -0
- package/bundle/packages/core/dist/lib/metadata/metadata.js +28 -0
- package/bundle/packages/core/dist/lib/store/store.js +24 -0
- package/bundle/packages/interfaces/dist/connection_manager.js +9 -0
- package/bundle/packages/interfaces/dist/health_status.js +17 -0
- package/bundle/packages/interfaces/dist/protocols.js +92 -0
- package/bundle/packages/interfaces/dist/waku.js +7 -0
- package/bundle/packages/proto/dist/generated/filter.js +447 -0
- package/bundle/packages/proto/dist/generated/filter_v2.js +426 -0
- package/bundle/packages/proto/dist/generated/light_push.js +550 -0
- package/bundle/packages/proto/dist/generated/message.js +215 -0
- package/bundle/packages/proto/dist/generated/metadata.js +132 -0
- package/bundle/packages/proto/dist/generated/peer_exchange.js +211 -0
- package/bundle/packages/proto/dist/generated/sds_message.js +172 -0
- package/bundle/packages/proto/dist/generated/store_v3.js +492 -0
- package/bundle/packages/proto/dist/generated/topic_only_message.js +63 -0
- package/bundle/packages/rln/dist/codec.js +92 -0
- package/bundle/packages/rln/dist/contract/constants.js +14 -7
- package/bundle/packages/rln/dist/contract/rln_base_contract.js +2 -1
- package/bundle/packages/rln/dist/contract/rln_contract.js +109 -0
- package/bundle/packages/rln/dist/credentials_manager.js +45 -4
- package/bundle/packages/rln/dist/identity.js +2 -1
- package/bundle/packages/rln/dist/keystore/keystore.js +30 -9
- package/bundle/packages/rln/dist/message.js +59 -0
- package/bundle/packages/rln/dist/proof.js +54 -0
- package/bundle/packages/rln/dist/resources/verification_key.js +112 -0
- package/bundle/packages/rln/dist/resources/witness_calculator.js +1 -1
- package/bundle/packages/rln/dist/rln.js +36 -4
- package/bundle/packages/rln/dist/root_tracker.js +76 -0
- package/bundle/packages/rln/dist/utils/bytes.js +70 -31
- package/bundle/packages/rln/dist/utils/epoch.js +23 -1
- package/bundle/packages/rln/dist/utils/hash.js +10 -0
- package/bundle/packages/rln/dist/zerokit.js +99 -2
- package/bundle/packages/utils/dist/bytes/index.js +31 -0
- package/bundle/resources/rln.wasm +0 -0
- package/bundle/resources/rln_final.zkey +0 -0
- package/bundle/resources/verification_key.d.ts +13 -0
- package/bundle/resources/verification_key.js +112 -0
- package/bundle/resources/witness_calculator.d.ts +7 -21
- package/bundle/resources/witness_calculator.js +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/codec.d.ts +40 -0
- package/dist/codec.js +79 -0
- package/dist/codec.js.map +1 -0
- package/dist/codec.test-utils.d.ts +37 -0
- package/dist/codec.test-utils.js +61 -0
- package/dist/codec.test-utils.js.map +1 -0
- package/dist/contract/constants.d.ts +10 -3
- package/dist/contract/constants.js +13 -6
- package/dist/contract/constants.js.map +1 -1
- package/dist/contract/index.d.ts +1 -0
- package/dist/contract/index.js +1 -0
- package/dist/contract/index.js.map +1 -1
- package/dist/contract/rln_base_contract.js +2 -1
- package/dist/contract/rln_base_contract.js.map +1 -1
- package/dist/contract/rln_contract.d.ts +17 -0
- package/dist/contract/rln_contract.js +107 -0
- package/dist/contract/rln_contract.js.map +1 -0
- package/dist/contract/test_setup.d.ts +26 -0
- package/dist/contract/test_setup.js +56 -0
- package/dist/contract/test_setup.js.map +1 -0
- package/dist/contract/test_utils.d.ts +39 -0
- package/dist/contract/test_utils.js +118 -0
- package/dist/contract/test_utils.js.map +1 -0
- package/dist/credentials_manager.d.ts +14 -2
- package/dist/credentials_manager.js +45 -4
- package/dist/credentials_manager.js.map +1 -1
- package/dist/identity.js +2 -1
- package/dist/identity.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/keystore/keystore.js +30 -9
- package/dist/keystore/keystore.js.map +1 -1
- package/dist/message.d.ts +19 -0
- package/dist/message.js +51 -0
- package/dist/message.js.map +1 -0
- package/dist/proof.d.ts +21 -0
- package/dist/proof.js +50 -0
- package/dist/proof.js.map +1 -0
- package/dist/resources/rln.wasm +0 -0
- package/dist/resources/rln_final.zkey +0 -0
- package/dist/resources/verification_key.d.ts +13 -0
- package/dist/resources/verification_key.js +112 -0
- package/dist/resources/witness_calculator.d.ts +7 -21
- package/dist/resources/witness_calculator.js +1 -1
- package/dist/rln.d.ts +9 -0
- package/dist/rln.js +32 -4
- package/dist/rln.js.map +1 -1
- package/dist/root_tracker.d.ts +10 -0
- package/dist/root_tracker.js +75 -0
- package/dist/root_tracker.js.map +1 -0
- package/dist/utils/bytes.d.ts +31 -9
- package/dist/utils/bytes.js +70 -31
- package/dist/utils/bytes.js.map +1 -1
- package/dist/zerokit.d.ts +11 -0
- package/dist/zerokit.js +97 -1
- package/dist/zerokit.js.map +1 -1
- package/package.json +1 -1
- package/src/codec.test-utils.ts +88 -0
- package/src/codec.ts +138 -0
- package/src/contract/constants.ts +16 -6
- package/src/contract/index.ts +1 -0
- package/src/contract/rln_base_contract.ts +2 -1
- package/src/contract/rln_contract.ts +147 -0
- package/src/contract/test_setup.ts +86 -0
- package/src/contract/test_utils.ts +179 -0
- package/src/credentials_manager.ts +72 -8
- package/src/identity.ts +2 -1
- package/src/index.ts +11 -1
- package/src/keystore/keystore.ts +32 -9
- package/src/message.ts +73 -0
- package/src/proof.ts +69 -0
- package/src/resources/verification_key.d.ts +13 -0
- package/src/resources/witness_calculator.d.ts +7 -21
- package/src/rln.ts +65 -5
- package/src/root_tracker.ts +92 -0
- package/src/utils/bytes.ts +73 -36
- package/src/zerokit.ts +217 -1
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { decodeMessage } from '../../../../node_modules/protons-runtime/dist/src/decode.js';
|
|
2
|
+
import { encodeMessage } from '../../../../node_modules/protons-runtime/dist/src/encode.js';
|
|
3
|
+
import '../../../../node_modules/protons-runtime/dist/src/codec.js';
|
|
4
|
+
import { message } from '../../../../node_modules/protons-runtime/dist/src/codecs/message.js';
|
|
5
|
+
import '../../../../node_modules/protons-runtime/dist/src/utils/float.js';
|
|
6
|
+
import '../../../../node_modules/protons-runtime/dist/src/utils/longbits.js';
|
|
7
|
+
import '../../../../node_modules/protons-runtime/dist/src/utils/writer.js';
|
|
8
|
+
|
|
9
|
+
/* eslint-disable import/export */
|
|
10
|
+
/* eslint-disable complexity */
|
|
11
|
+
/* eslint-disable @typescript-eslint/no-namespace */
|
|
12
|
+
/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */
|
|
13
|
+
/* eslint-disable @typescript-eslint/no-empty-interface */
|
|
14
|
+
/* eslint-disable import/consistent-type-specifier-style */
|
|
15
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
16
|
+
var TopicOnlyMessage;
|
|
17
|
+
(function (TopicOnlyMessage) {
|
|
18
|
+
let _codec;
|
|
19
|
+
TopicOnlyMessage.codec = () => {
|
|
20
|
+
if (_codec == null) {
|
|
21
|
+
_codec = message((obj, w, opts = {}) => {
|
|
22
|
+
if (opts.lengthDelimited !== false) {
|
|
23
|
+
w.fork();
|
|
24
|
+
}
|
|
25
|
+
if ((obj.contentTopic != null && obj.contentTopic !== '')) {
|
|
26
|
+
w.uint32(18);
|
|
27
|
+
w.string(obj.contentTopic);
|
|
28
|
+
}
|
|
29
|
+
if (opts.lengthDelimited !== false) {
|
|
30
|
+
w.ldelim();
|
|
31
|
+
}
|
|
32
|
+
}, (reader, length, opts = {}) => {
|
|
33
|
+
const obj = {
|
|
34
|
+
contentTopic: ''
|
|
35
|
+
};
|
|
36
|
+
const end = length == null ? reader.len : reader.pos + length;
|
|
37
|
+
while (reader.pos < end) {
|
|
38
|
+
const tag = reader.uint32();
|
|
39
|
+
switch (tag >>> 3) {
|
|
40
|
+
case 2: {
|
|
41
|
+
obj.contentTopic = reader.string();
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
default: {
|
|
45
|
+
reader.skipType(tag & 7);
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return obj;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return _codec;
|
|
54
|
+
};
|
|
55
|
+
TopicOnlyMessage.encode = (obj) => {
|
|
56
|
+
return encodeMessage(obj, TopicOnlyMessage.codec());
|
|
57
|
+
};
|
|
58
|
+
TopicOnlyMessage.decode = (buf, opts) => {
|
|
59
|
+
return decodeMessage(buf, TopicOnlyMessage.codec(), opts);
|
|
60
|
+
};
|
|
61
|
+
})(TopicOnlyMessage || (TopicOnlyMessage = {}));
|
|
62
|
+
|
|
63
|
+
export { TopicOnlyMessage };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import '../../../node_modules/multiformats/dist/src/bases/base10.js';
|
|
2
|
+
import '../../../node_modules/multiformats/dist/src/bases/base16.js';
|
|
3
|
+
import '../../../node_modules/multiformats/dist/src/bases/base2.js';
|
|
4
|
+
import '../../../node_modules/multiformats/dist/src/bases/base256emoji.js';
|
|
5
|
+
import '../../../node_modules/multiformats/dist/src/bases/base32.js';
|
|
6
|
+
import '../../../node_modules/multiformats/dist/src/bases/base36.js';
|
|
7
|
+
import '../../../node_modules/multiformats/dist/src/bases/base58.js';
|
|
8
|
+
import '../../../node_modules/multiformats/dist/src/bases/base64.js';
|
|
9
|
+
import '../../../node_modules/multiformats/dist/src/bases/base8.js';
|
|
10
|
+
import '../../../node_modules/multiformats/dist/src/bases/identity.js';
|
|
11
|
+
import '../../../node_modules/multiformats/dist/src/codecs/json.js';
|
|
12
|
+
import { Logger } from '../../utils/dist/logger.js';
|
|
13
|
+
import { toRLNSignal, RlnMessage } from './message.js';
|
|
14
|
+
|
|
15
|
+
const log = new Logger("waku:rln:encoder");
|
|
16
|
+
class RLNEncoder {
|
|
17
|
+
encoder;
|
|
18
|
+
rlnInstance;
|
|
19
|
+
index;
|
|
20
|
+
idSecretHash;
|
|
21
|
+
constructor(encoder, rlnInstance, index, identityCredential) {
|
|
22
|
+
this.encoder = encoder;
|
|
23
|
+
this.rlnInstance = rlnInstance;
|
|
24
|
+
this.index = index;
|
|
25
|
+
if (index < 0)
|
|
26
|
+
throw new Error("Invalid membership index");
|
|
27
|
+
this.idSecretHash = identityCredential.IDSecretHash;
|
|
28
|
+
}
|
|
29
|
+
async toWire(message) {
|
|
30
|
+
message.rateLimitProof = await this.generateProof(message);
|
|
31
|
+
log.info("Proof generated", message.rateLimitProof);
|
|
32
|
+
return this.encoder.toWire(message);
|
|
33
|
+
}
|
|
34
|
+
async toProtoObj(message) {
|
|
35
|
+
const protoMessage = await this.encoder.toProtoObj(message);
|
|
36
|
+
if (!protoMessage)
|
|
37
|
+
return;
|
|
38
|
+
protoMessage.contentTopic = this.contentTopic;
|
|
39
|
+
protoMessage.rateLimitProof = await this.generateProof(message);
|
|
40
|
+
log.info("Proof generated", protoMessage.rateLimitProof);
|
|
41
|
+
return protoMessage;
|
|
42
|
+
}
|
|
43
|
+
async generateProof(message) {
|
|
44
|
+
const signal = toRLNSignal(this.contentTopic, message);
|
|
45
|
+
return this.rlnInstance.zerokit.generateRLNProof(signal, this.index, message.timestamp, this.idSecretHash);
|
|
46
|
+
}
|
|
47
|
+
get pubsubTopic() {
|
|
48
|
+
return this.encoder.pubsubTopic;
|
|
49
|
+
}
|
|
50
|
+
get routingInfo() {
|
|
51
|
+
return this.encoder.routingInfo;
|
|
52
|
+
}
|
|
53
|
+
get contentTopic() {
|
|
54
|
+
return this.encoder.contentTopic;
|
|
55
|
+
}
|
|
56
|
+
get ephemeral() {
|
|
57
|
+
return this.encoder.ephemeral;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const createRLNEncoder = (options) => {
|
|
61
|
+
return new RLNEncoder(options.encoder, options.rlnInstance, options.index, options.credential);
|
|
62
|
+
};
|
|
63
|
+
class RLNDecoder {
|
|
64
|
+
rlnInstance;
|
|
65
|
+
decoder;
|
|
66
|
+
constructor(rlnInstance, decoder) {
|
|
67
|
+
this.rlnInstance = rlnInstance;
|
|
68
|
+
this.decoder = decoder;
|
|
69
|
+
}
|
|
70
|
+
get pubsubTopic() {
|
|
71
|
+
return this.decoder.pubsubTopic;
|
|
72
|
+
}
|
|
73
|
+
get contentTopic() {
|
|
74
|
+
return this.decoder.contentTopic;
|
|
75
|
+
}
|
|
76
|
+
fromWireToProtoObj(bytes) {
|
|
77
|
+
const protoMessage = this.decoder.fromWireToProtoObj(bytes);
|
|
78
|
+
log.info("Message decoded", protoMessage);
|
|
79
|
+
return Promise.resolve(protoMessage);
|
|
80
|
+
}
|
|
81
|
+
async fromProtoObj(pubsubTopic, proto) {
|
|
82
|
+
const msg = await this.decoder.fromProtoObj(pubsubTopic, proto);
|
|
83
|
+
if (!msg)
|
|
84
|
+
return;
|
|
85
|
+
return new RlnMessage(this.rlnInstance, msg, proto.rateLimitProof);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const createRLNDecoder = (options) => {
|
|
89
|
+
return new RLNDecoder(options.rlnInstance, options.decoder);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export { RLNDecoder, RLNEncoder, createRLNDecoder, createRLNEncoder };
|
|
@@ -17,16 +17,23 @@ const PRICE_CALCULATOR_CONTRACT = {
|
|
|
17
17
|
* @see https://github.com/waku-org/specs/blob/master/standards/core/rln-contract.md#implementation-suggestions
|
|
18
18
|
*/
|
|
19
19
|
const RATE_LIMIT_TIERS = {
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
LOW: 20, // Suggested minimum rate - 20 messages per epoch
|
|
21
|
+
MEDIUM: 200,
|
|
22
|
+
HIGH: 600 // Suggested maximum rate - 600 messages per epoch
|
|
22
23
|
};
|
|
23
24
|
// Global rate limit parameters
|
|
24
25
|
const RATE_LIMIT_PARAMS = {
|
|
25
|
-
MIN_RATE: RATE_LIMIT_TIERS.
|
|
26
|
-
MAX_RATE: RATE_LIMIT_TIERS.
|
|
27
|
-
MAX_TOTAL_RATE: 160_000,
|
|
28
|
-
EPOCH_LENGTH: 600
|
|
26
|
+
MIN_RATE: RATE_LIMIT_TIERS.LOW,
|
|
27
|
+
MAX_RATE: RATE_LIMIT_TIERS.HIGH,
|
|
28
|
+
MAX_TOTAL_RATE: 160_000, // Maximum total rate limit across all memberships
|
|
29
|
+
EPOCH_LENGTH: 600 // Epoch length in seconds (10 minutes)
|
|
29
30
|
};
|
|
31
|
+
/**
|
|
32
|
+
* Default Q value for the RLN contract
|
|
33
|
+
* This is the upper bound for the ID commitment
|
|
34
|
+
* @see https://github.com/waku-org/specs/blob/master/standards/core/rln-contract.md#implementation-suggestions
|
|
35
|
+
*/
|
|
36
|
+
const RLN_Q = BigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
|
30
37
|
const DEFAULT_RATE_LIMIT = RATE_LIMIT_PARAMS.MAX_RATE;
|
|
31
38
|
|
|
32
|
-
export { DEFAULT_RATE_LIMIT, PRICE_CALCULATOR_CONTRACT, RATE_LIMIT_PARAMS, RATE_LIMIT_TIERS, RLN_CONTRACT };
|
|
39
|
+
export { DEFAULT_RATE_LIMIT, PRICE_CALCULATOR_CONTRACT, RATE_LIMIT_PARAMS, RATE_LIMIT_TIERS, RLN_CONTRACT, RLN_Q };
|
|
@@ -10,6 +10,7 @@ import '../../../../node_modules/multiformats/dist/src/bases/base8.js';
|
|
|
10
10
|
import '../../../../node_modules/multiformats/dist/src/bases/identity.js';
|
|
11
11
|
import '../../../../node_modules/multiformats/dist/src/codecs/json.js';
|
|
12
12
|
import { Logger } from '../../../utils/dist/logger.js';
|
|
13
|
+
import { BytesUtils } from '../utils/bytes.js';
|
|
13
14
|
import { RLN_ABI } from './abi/rln.js';
|
|
14
15
|
import { DEFAULT_RATE_LIMIT, RATE_LIMIT_PARAMS, PRICE_CALCULATOR_CONTRACT } from './constants.js';
|
|
15
16
|
import { MembershipState } from './types.js';
|
|
@@ -413,7 +414,7 @@ class RLNBaseContract {
|
|
|
413
414
|
async registerWithPermitAndErase(identity, permit, idCommitmentsToErase) {
|
|
414
415
|
try {
|
|
415
416
|
log.info(`Registering identity with permit and rate limit: ${this.rateLimit} messages/epoch`);
|
|
416
|
-
const txRegisterResponse = await this.contract.registerWithPermit(permit.owner, permit.deadline, permit.v, permit.r, permit.s, identity.
|
|
417
|
+
const txRegisterResponse = await this.contract.registerWithPermit(permit.owner, permit.deadline, permit.v, permit.r, permit.s, BytesUtils.buildBigIntFromUint8ArrayBE(identity.IDCommitment), this.rateLimit, idCommitmentsToErase.map((id) => BigNumber.from(id)));
|
|
417
418
|
const txRegisterReceipt = await txRegisterResponse.wait();
|
|
418
419
|
const memberRegistered = txRegisterReceipt.events?.find((event) => event.event === "MembershipRegistered");
|
|
419
420
|
if (!memberRegistered || !memberRegistered.args) {
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { hexToBytes } from '../../../utils/dist/bytes/index.js';
|
|
2
|
+
import { Logger } from '../../../utils/dist/logger.js';
|
|
3
|
+
import { MerkleRootTracker } from '../root_tracker.js';
|
|
4
|
+
import { BytesUtils } from '../utils/bytes.js';
|
|
5
|
+
import { RLNBaseContract } from './rln_base_contract.js';
|
|
6
|
+
import { BigNumber } from '../../../../node_modules/@ethersproject/bignumber/lib.esm/bignumber.js';
|
|
7
|
+
|
|
8
|
+
const log = new Logger("waku:rln:contract");
|
|
9
|
+
class RLNContract extends RLNBaseContract {
|
|
10
|
+
instance;
|
|
11
|
+
merkleRootTracker;
|
|
12
|
+
/**
|
|
13
|
+
* Asynchronous initializer for RLNContract.
|
|
14
|
+
* Allows injecting a mocked contract for testing purposes.
|
|
15
|
+
*/
|
|
16
|
+
static async init(rlnInstance, options) {
|
|
17
|
+
const rlnContract = new RLNContract(rlnInstance, options);
|
|
18
|
+
return rlnContract;
|
|
19
|
+
}
|
|
20
|
+
constructor(rlnInstance, options) {
|
|
21
|
+
super(options);
|
|
22
|
+
this.instance = rlnInstance;
|
|
23
|
+
const initialRoot = rlnInstance.zerokit.getMerkleRoot();
|
|
24
|
+
this.merkleRootTracker = new MerkleRootTracker(5, initialRoot);
|
|
25
|
+
}
|
|
26
|
+
processEvents(events) {
|
|
27
|
+
const toRemoveTable = new Map();
|
|
28
|
+
const toInsertTable = new Map();
|
|
29
|
+
events.forEach((evt) => {
|
|
30
|
+
if (!evt.args) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (evt.event === "MembershipErased" ||
|
|
34
|
+
evt.event === "MembershipExpired") {
|
|
35
|
+
let index = evt.args.index;
|
|
36
|
+
if (!index) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (typeof index === "number" || typeof index === "string") {
|
|
40
|
+
index = BigNumber.from(index);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
log.error("Index is not a number or string", {
|
|
44
|
+
index,
|
|
45
|
+
event: evt
|
|
46
|
+
});
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const toRemoveVal = toRemoveTable.get(evt.blockNumber);
|
|
50
|
+
if (toRemoveVal != undefined) {
|
|
51
|
+
toRemoveVal.push(index.toNumber());
|
|
52
|
+
toRemoveTable.set(evt.blockNumber, toRemoveVal);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
toRemoveTable.set(evt.blockNumber, [index.toNumber()]);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else if (evt.event === "MembershipRegistered") {
|
|
59
|
+
let eventsPerBlock = toInsertTable.get(evt.blockNumber);
|
|
60
|
+
if (eventsPerBlock == undefined) {
|
|
61
|
+
eventsPerBlock = [];
|
|
62
|
+
}
|
|
63
|
+
eventsPerBlock.push(evt);
|
|
64
|
+
toInsertTable.set(evt.blockNumber, eventsPerBlock);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
this.removeMembers(this.instance, toRemoveTable);
|
|
68
|
+
this.insertMembers(this.instance, toInsertTable);
|
|
69
|
+
}
|
|
70
|
+
insertMembers(rlnInstance, toInsert) {
|
|
71
|
+
toInsert.forEach((events, blockNumber) => {
|
|
72
|
+
events.forEach((evt) => {
|
|
73
|
+
if (!evt.args)
|
|
74
|
+
return;
|
|
75
|
+
const _idCommitment = evt.args.idCommitment;
|
|
76
|
+
let index = evt.args.index;
|
|
77
|
+
if (!_idCommitment || !index) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (typeof index === "number" || typeof index === "string") {
|
|
81
|
+
index = BigNumber.from(index);
|
|
82
|
+
}
|
|
83
|
+
const idCommitment = BytesUtils.zeroPadLE(hexToBytes(_idCommitment), 32);
|
|
84
|
+
rlnInstance.zerokit.insertMember(idCommitment);
|
|
85
|
+
const numericIndex = index.toNumber();
|
|
86
|
+
this._members.set(numericIndex, {
|
|
87
|
+
index,
|
|
88
|
+
idCommitment: _idCommitment
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
const currentRoot = rlnInstance.zerokit.getMerkleRoot();
|
|
92
|
+
this.merkleRootTracker.pushRoot(blockNumber, currentRoot);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
removeMembers(rlnInstance, toRemove) {
|
|
96
|
+
const removeDescending = new Map([...toRemove].reverse());
|
|
97
|
+
removeDescending.forEach((indexes, blockNumber) => {
|
|
98
|
+
indexes.forEach((index) => {
|
|
99
|
+
if (this._members.has(index)) {
|
|
100
|
+
this._members.delete(index);
|
|
101
|
+
rlnInstance.zerokit.deleteMember(index);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
this.merkleRootTracker.backFill(blockNumber);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export { RLNContract };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { hmac } from '../../../node_modules/@noble/hashes/esm/hmac.js';
|
|
2
|
+
import { sha256 } from '../../../node_modules/@noble/hashes/esm/sha2.js';
|
|
1
3
|
import '../../../node_modules/multiformats/dist/src/bases/base10.js';
|
|
2
4
|
import '../../../node_modules/multiformats/dist/src/bases/base16.js';
|
|
3
5
|
import '../../../node_modules/multiformats/dist/src/bases/base2.js';
|
|
@@ -10,15 +12,18 @@ import '../../../node_modules/multiformats/dist/src/bases/base8.js';
|
|
|
10
12
|
import '../../../node_modules/multiformats/dist/src/bases/identity.js';
|
|
11
13
|
import '../../../node_modules/multiformats/dist/src/codecs/json.js';
|
|
12
14
|
import { Logger } from '../../utils/dist/logger.js';
|
|
13
|
-
import { RLN_CONTRACT } from './contract/constants.js';
|
|
15
|
+
import { RLN_CONTRACT, RLN_Q } from './contract/constants.js';
|
|
14
16
|
import { RLNBaseContract } from './contract/rln_base_contract.js';
|
|
17
|
+
import { IdentityCredential } from './identity.js';
|
|
15
18
|
import { Keystore } from './keystore/keystore.js';
|
|
19
|
+
import { BytesUtils } from './utils/bytes.js';
|
|
16
20
|
import { extractMetaMaskSigner } from './utils/metamask.js';
|
|
17
21
|
import './utils/epoch.js';
|
|
18
22
|
|
|
19
23
|
const log = new Logger("waku:credentials");
|
|
20
24
|
/**
|
|
21
25
|
* Manages credentials for RLN
|
|
26
|
+
* This is a lightweight implementation of the RLN contract that doesn't require Zerokit
|
|
22
27
|
* It is used to register membership and generate identity credentials
|
|
23
28
|
*/
|
|
24
29
|
class RLNCredentialsManager {
|
|
@@ -59,7 +64,7 @@ class RLNCredentialsManager {
|
|
|
59
64
|
this.contract = await RLNBaseContract.create({
|
|
60
65
|
address: address,
|
|
61
66
|
signer: signer,
|
|
62
|
-
rateLimit: rateLimit ?? this.zerokit
|
|
67
|
+
rateLimit: rateLimit ?? this.zerokit?.rateLimit
|
|
63
68
|
});
|
|
64
69
|
log.info("RLNCredentialsManager successfully started");
|
|
65
70
|
this.started = true;
|
|
@@ -80,8 +85,15 @@ class RLNCredentialsManager {
|
|
|
80
85
|
log.info("Registering membership");
|
|
81
86
|
let identity = "identity" in options && options.identity;
|
|
82
87
|
if ("signature" in options) {
|
|
83
|
-
log.info("
|
|
84
|
-
|
|
88
|
+
log.info("Generating identity from signature");
|
|
89
|
+
if (this.zerokit) {
|
|
90
|
+
log.info("Using Zerokit to generate identity");
|
|
91
|
+
identity = this.zerokit.generateSeededIdentityCredential(options.signature);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
log.info("Using local implementation to generate identity");
|
|
95
|
+
identity = await this.generateSeededIdentityCredential(options.signature);
|
|
96
|
+
}
|
|
85
97
|
}
|
|
86
98
|
if (!identity) {
|
|
87
99
|
log.error("Missing signature or identity to register membership");
|
|
@@ -170,6 +182,35 @@ class RLNCredentialsManager {
|
|
|
170
182
|
throw Error(`Failed to verify chain coordinates: credentials chainID=${chainId} is not equal to registryContract chainID=${currentChainId}`);
|
|
171
183
|
}
|
|
172
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* Generates an identity credential from a seed string
|
|
187
|
+
* This is a pure implementation that doesn't rely on Zerokit
|
|
188
|
+
* @param seed A string seed to generate the identity from
|
|
189
|
+
* @returns IdentityCredential
|
|
190
|
+
*/
|
|
191
|
+
async generateSeededIdentityCredential(seed) {
|
|
192
|
+
log.info("Generating seeded identity credential");
|
|
193
|
+
// Convert the seed to bytes
|
|
194
|
+
const encoder = new TextEncoder();
|
|
195
|
+
const seedBytes = encoder.encode(seed);
|
|
196
|
+
// Generate deterministic values using HMAC-SHA256
|
|
197
|
+
// We use different context strings for each component to ensure they're different
|
|
198
|
+
const idTrapdoorBE = hmac(sha256, seedBytes, encoder.encode("IDTrapdoor"));
|
|
199
|
+
const idNullifierBE = hmac(sha256, seedBytes, encoder.encode("IDNullifier"));
|
|
200
|
+
const combinedBytes = new Uint8Array([...idTrapdoorBE, ...idNullifierBE]);
|
|
201
|
+
const idSecretHashBE = sha256(combinedBytes);
|
|
202
|
+
const idCommitmentRawBE = sha256(idSecretHashBE);
|
|
203
|
+
const idCommitmentBE = this.reduceIdCommitment(idCommitmentRawBE);
|
|
204
|
+
log.info("Successfully generated identity credential, storing in Big Endian format");
|
|
205
|
+
return new IdentityCredential(idTrapdoorBE, idNullifierBE, idSecretHashBE, idCommitmentBE);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Helper: take 32-byte BE, reduce mod Q, return 32-byte BE
|
|
209
|
+
*/
|
|
210
|
+
reduceIdCommitment(bytesBE, limit = RLN_Q) {
|
|
211
|
+
const nBE = BytesUtils.buildBigIntFromUint8ArrayBE(bytesBE);
|
|
212
|
+
return BytesUtils.bigIntToUint8Array32BE(nBE % limit);
|
|
213
|
+
}
|
|
173
214
|
}
|
|
174
215
|
|
|
175
216
|
export { RLNCredentialsManager };
|
|
@@ -14,7 +14,8 @@ class IdentityCredential {
|
|
|
14
14
|
this.IDNullifier = IDNullifier;
|
|
15
15
|
this.IDSecretHash = IDSecretHash;
|
|
16
16
|
this.IDCommitment = IDCommitment;
|
|
17
|
-
this.IDCommitmentBigInt =
|
|
17
|
+
this.IDCommitmentBigInt =
|
|
18
|
+
BytesUtils.buildBigIntFromUint8ArrayBE(IDCommitment);
|
|
18
19
|
}
|
|
19
20
|
static fromBytes(memKeys) {
|
|
20
21
|
if (memKeys.length < 128) {
|
|
@@ -166,13 +166,18 @@ class Keystore {
|
|
|
166
166
|
const idTrapdoorLE = Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idTrapdoor", []));
|
|
167
167
|
const idNullifierLE = Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idNullifier", []));
|
|
168
168
|
const idSecretHashLE = Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idSecretHash", []));
|
|
169
|
-
|
|
169
|
+
// Big Endian
|
|
170
|
+
const idCommitmentBE = BytesUtils.switchEndianness(idCommitmentLE);
|
|
171
|
+
const idTrapdoorBE = BytesUtils.switchEndianness(idTrapdoorLE);
|
|
172
|
+
const idNullifierBE = BytesUtils.switchEndianness(idNullifierLE);
|
|
173
|
+
const idSecretHashBE = BytesUtils.switchEndianness(idSecretHashLE);
|
|
174
|
+
const idCommitmentBigInt = BytesUtils.buildBigIntFromUint8ArrayBE(idCommitmentBE);
|
|
170
175
|
return {
|
|
171
176
|
identity: {
|
|
172
|
-
IDCommitment:
|
|
173
|
-
IDTrapdoor:
|
|
174
|
-
IDNullifier:
|
|
175
|
-
IDSecretHash:
|
|
177
|
+
IDCommitment: idCommitmentBE,
|
|
178
|
+
IDTrapdoor: idTrapdoorBE,
|
|
179
|
+
IDNullifier: idNullifierBE,
|
|
180
|
+
IDSecretHash: idSecretHashBE,
|
|
176
181
|
IDCommitmentBigInt: idCommitmentBigInt
|
|
177
182
|
},
|
|
178
183
|
membership: {
|
|
@@ -209,15 +214,31 @@ class Keystore {
|
|
|
209
214
|
}
|
|
210
215
|
// follows nwaku implementation
|
|
211
216
|
// https://github.com/waku-org/nwaku/blob/f05528d4be3d3c876a8b07f9bb7dfaae8aa8ec6e/waku/waku_keystore/protocol_types.nim#L98
|
|
217
|
+
// IdentityCredential is stored in Big Endian format => switch to Little Endian
|
|
212
218
|
static fromIdentityToBytes(options) {
|
|
213
219
|
const { IDCommitment, IDNullifier, IDSecretHash, IDTrapdoor } = options.identity;
|
|
220
|
+
const idCommitmentLE = BytesUtils.switchEndianness(IDCommitment);
|
|
221
|
+
const idNullifierLE = BytesUtils.switchEndianness(IDNullifier);
|
|
222
|
+
const idSecretHashLE = BytesUtils.switchEndianness(IDSecretHash);
|
|
223
|
+
const idTrapdoorLE = BytesUtils.switchEndianness(IDTrapdoor);
|
|
224
|
+
// eslint-disable-next-line no-console
|
|
225
|
+
console.log({
|
|
226
|
+
idCommitmentBE: IDCommitment,
|
|
227
|
+
idCommitmentLE,
|
|
228
|
+
idNullifierBE: IDNullifier,
|
|
229
|
+
idNullifierLE,
|
|
230
|
+
idSecretHashBE: IDSecretHash,
|
|
231
|
+
idSecretHashLE,
|
|
232
|
+
idTrapdoorBE: IDTrapdoor,
|
|
233
|
+
idTrapdoorLE
|
|
234
|
+
});
|
|
214
235
|
return utf8ToBytes(JSON.stringify({
|
|
215
236
|
treeIndex: options.membership.treeIndex,
|
|
216
237
|
identityCredential: {
|
|
217
|
-
idCommitment: Array.from(
|
|
218
|
-
idNullifier: Array.from(
|
|
219
|
-
idSecretHash: Array.from(
|
|
220
|
-
idTrapdoor: Array.from(
|
|
238
|
+
idCommitment: Array.from(idCommitmentLE),
|
|
239
|
+
idNullifier: Array.from(idNullifierLE),
|
|
240
|
+
idSecretHash: Array.from(idSecretHashLE),
|
|
241
|
+
idTrapdoor: Array.from(idTrapdoorLE)
|
|
221
242
|
},
|
|
222
243
|
membershipContract: {
|
|
223
244
|
chainId: options.membership.chainId,
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Version } from '../../core/dist/lib/message/version_0.js';
|
|
2
|
+
import '../../core/dist/lib/filter/filter.js';
|
|
3
|
+
import '../../core/dist/lib/light_push/light_push.js';
|
|
4
|
+
import '../../core/dist/lib/store/store.js';
|
|
5
|
+
import '../../core/dist/lib/connection_manager/connection_manager.js';
|
|
6
|
+
import { utf8ToBytes } from '../../utils/dist/bytes/index.js';
|
|
7
|
+
import '../../../node_modules/debug/src/browser.js';
|
|
8
|
+
import '../../core/dist/lib/metadata/metadata.js';
|
|
9
|
+
import { epochBytesToInt } from './utils/epoch.js';
|
|
10
|
+
|
|
11
|
+
function toRLNSignal(contentTopic, msg) {
|
|
12
|
+
const contentTopicBytes = utf8ToBytes(contentTopic ?? "");
|
|
13
|
+
return new Uint8Array([...(msg.payload ?? []), ...contentTopicBytes]);
|
|
14
|
+
}
|
|
15
|
+
class RlnMessage {
|
|
16
|
+
rlnInstance;
|
|
17
|
+
msg;
|
|
18
|
+
rateLimitProof;
|
|
19
|
+
pubsubTopic = "";
|
|
20
|
+
version = Version;
|
|
21
|
+
constructor(rlnInstance, msg, rateLimitProof) {
|
|
22
|
+
this.rlnInstance = rlnInstance;
|
|
23
|
+
this.msg = msg;
|
|
24
|
+
this.rateLimitProof = rateLimitProof;
|
|
25
|
+
}
|
|
26
|
+
verify(roots) {
|
|
27
|
+
return this.rateLimitProof
|
|
28
|
+
? this.rlnInstance.zerokit.verifyWithRoots(this.rateLimitProof, toRLNSignal(this.msg.contentTopic, this.msg), roots) // this.rlnInstance.verifyRLNProof once issue status-im/nwaku#1248 is fixed
|
|
29
|
+
: undefined;
|
|
30
|
+
}
|
|
31
|
+
verifyNoRoot() {
|
|
32
|
+
return this.rateLimitProof
|
|
33
|
+
? this.rlnInstance.zerokit.verifyWithNoRoot(this.rateLimitProof, toRLNSignal(this.msg.contentTopic, this.msg)) // this.rlnInstance.verifyRLNProof once issue status-im/nwaku#1248 is fixed
|
|
34
|
+
: undefined;
|
|
35
|
+
}
|
|
36
|
+
get payload() {
|
|
37
|
+
return this.msg.payload;
|
|
38
|
+
}
|
|
39
|
+
get contentTopic() {
|
|
40
|
+
return this.msg.contentTopic;
|
|
41
|
+
}
|
|
42
|
+
get timestamp() {
|
|
43
|
+
return this.msg.timestamp;
|
|
44
|
+
}
|
|
45
|
+
get ephemeral() {
|
|
46
|
+
return this.msg.ephemeral;
|
|
47
|
+
}
|
|
48
|
+
get meta() {
|
|
49
|
+
return this.msg.meta;
|
|
50
|
+
}
|
|
51
|
+
get epoch() {
|
|
52
|
+
const bytes = this.rateLimitProof?.epoch;
|
|
53
|
+
if (!bytes)
|
|
54
|
+
return undefined;
|
|
55
|
+
return epochBytesToInt(bytes);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { RlnMessage, toRLNSignal };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { BytesUtils } from './utils/bytes.js';
|
|
2
|
+
import { poseidonHash } from './utils/hash.js';
|
|
3
|
+
import './utils/epoch.js';
|
|
4
|
+
|
|
5
|
+
const proofOffset = 128;
|
|
6
|
+
const rootOffset = proofOffset + 32;
|
|
7
|
+
const epochOffset = rootOffset + 32;
|
|
8
|
+
const shareXOffset = epochOffset + 32;
|
|
9
|
+
const shareYOffset = shareXOffset + 32;
|
|
10
|
+
const nullifierOffset = shareYOffset + 32;
|
|
11
|
+
const rlnIdentifierOffset = nullifierOffset + 32;
|
|
12
|
+
class ProofMetadata {
|
|
13
|
+
nullifier;
|
|
14
|
+
shareX;
|
|
15
|
+
shareY;
|
|
16
|
+
externalNullifier;
|
|
17
|
+
constructor(nullifier, shareX, shareY, externalNullifier) {
|
|
18
|
+
this.nullifier = nullifier;
|
|
19
|
+
this.shareX = shareX;
|
|
20
|
+
this.shareY = shareY;
|
|
21
|
+
this.externalNullifier = externalNullifier;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
class Proof {
|
|
25
|
+
proof;
|
|
26
|
+
merkleRoot;
|
|
27
|
+
epoch;
|
|
28
|
+
shareX;
|
|
29
|
+
shareY;
|
|
30
|
+
nullifier;
|
|
31
|
+
rlnIdentifier;
|
|
32
|
+
constructor(proofBytes) {
|
|
33
|
+
if (proofBytes.length < rlnIdentifierOffset) {
|
|
34
|
+
throw new Error("invalid proof");
|
|
35
|
+
}
|
|
36
|
+
// parse the proof as proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32>
|
|
37
|
+
this.proof = proofBytes.subarray(0, proofOffset);
|
|
38
|
+
this.merkleRoot = proofBytes.subarray(proofOffset, rootOffset);
|
|
39
|
+
this.epoch = proofBytes.subarray(rootOffset, epochOffset);
|
|
40
|
+
this.shareX = proofBytes.subarray(epochOffset, shareXOffset);
|
|
41
|
+
this.shareY = proofBytes.subarray(shareXOffset, shareYOffset);
|
|
42
|
+
this.nullifier = proofBytes.subarray(shareYOffset, nullifierOffset);
|
|
43
|
+
this.rlnIdentifier = proofBytes.subarray(nullifierOffset, rlnIdentifierOffset);
|
|
44
|
+
}
|
|
45
|
+
extractMetadata() {
|
|
46
|
+
const externalNullifier = poseidonHash(this.epoch, this.rlnIdentifier);
|
|
47
|
+
return new ProofMetadata(this.nullifier, this.shareX, this.shareY, externalNullifier);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function proofToBytes(p) {
|
|
51
|
+
return BytesUtils.concatenate(p.proof, p.merkleRoot, p.epoch, p.shareX, p.shareY, p.nullifier, p.rlnIdentifier);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { Proof, proofToBytes };
|