@taquito/sapling 14.0.0-beta-RC.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/LICENSE +7 -0
- package/README.md +93 -0
- package/dist/lib/constants.js +8 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/error.js +72 -0
- package/dist/lib/error.js.map +1 -0
- package/dist/lib/sapling-forger/sapling-forger.js +101 -0
- package/dist/lib/sapling-forger/sapling-forger.js.map +1 -0
- package/dist/lib/sapling-keys/helpers.js +30 -0
- package/dist/lib/sapling-keys/helpers.js.map +1 -0
- package/dist/lib/sapling-keys/in-memory-proving-key.js +84 -0
- package/dist/lib/sapling-keys/in-memory-proving-key.js.map +1 -0
- package/dist/lib/sapling-keys/in-memory-spending-key.js +146 -0
- package/dist/lib/sapling-keys/in-memory-spending-key.js.map +1 -0
- package/dist/lib/sapling-keys/in-memory-viewing-key.js +101 -0
- package/dist/lib/sapling-keys/in-memory-viewing-key.js.map +1 -0
- package/dist/lib/sapling-module-wrapper.js +83 -0
- package/dist/lib/sapling-module-wrapper.js.map +1 -0
- package/dist/lib/sapling-state/sapling-state.js +171 -0
- package/dist/lib/sapling-state/sapling-state.js.map +1 -0
- package/dist/lib/sapling-state/utils.js +60 -0
- package/dist/lib/sapling-state/utils.js.map +1 -0
- package/dist/lib/sapling-tx-builder/sapling-transactions-builder.js +288 -0
- package/dist/lib/sapling-tx-builder/sapling-transactions-builder.js.map +1 -0
- package/dist/lib/sapling-tx-viewer/helpers.js +31 -0
- package/dist/lib/sapling-tx-viewer/helpers.js.map +1 -0
- package/dist/lib/sapling-tx-viewer/sapling-transaction-viewer.js +230 -0
- package/dist/lib/sapling-tx-viewer/sapling-transaction-viewer.js.map +1 -0
- package/dist/lib/taquito-sapling.js +293 -0
- package/dist/lib/taquito-sapling.js.map +1 -0
- package/dist/lib/types.js +3 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/version.js +9 -0
- package/dist/lib/version.js.map +1 -0
- package/dist/taquito-sapling.es6.js +1456 -0
- package/dist/taquito-sapling.es6.js.map +1 -0
- package/dist/taquito-sapling.umd.js +1485 -0
- package/dist/taquito-sapling.umd.js.map +1 -0
- package/dist/types/constants.d.ts +5 -0
- package/dist/types/error.d.ts +50 -0
- package/dist/types/sapling-forger/sapling-forger.d.ts +30 -0
- package/dist/types/sapling-keys/helpers.d.ts +2 -0
- package/dist/types/sapling-keys/in-memory-proving-key.d.ts +35 -0
- package/dist/types/sapling-keys/in-memory-spending-key.d.ts +53 -0
- package/dist/types/sapling-keys/in-memory-viewing-key.d.ts +48 -0
- package/dist/types/sapling-module-wrapper.d.ts +19 -0
- package/dist/types/sapling-state/sapling-state.d.ts +55 -0
- package/dist/types/sapling-state/utils.d.ts +22 -0
- package/dist/types/sapling-tx-builder/sapling-transactions-builder.d.ts +32 -0
- package/dist/types/sapling-tx-viewer/helpers.d.ts +11 -0
- package/dist/types/sapling-tx-viewer/sapling-transaction-viewer.d.ts +50 -0
- package/dist/types/taquito-sapling.d.ts +81 -0
- package/dist/types/types.d.ts +147 -0
- package/dist/types/version.d.ts +4 -0
- package/fetch-sapling-params.js +41 -0
- package/package.json +112 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, privateMap, value) {
|
|
12
|
+
if (!privateMap.has(receiver)) {
|
|
13
|
+
throw new TypeError("attempted to set private field on non-instance");
|
|
14
|
+
}
|
|
15
|
+
privateMap.set(receiver, value);
|
|
16
|
+
return value;
|
|
17
|
+
};
|
|
18
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, privateMap) {
|
|
19
|
+
if (!privateMap.has(receiver)) {
|
|
20
|
+
throw new TypeError("attempted to get private field on non-instance");
|
|
21
|
+
}
|
|
22
|
+
return privateMap.get(receiver);
|
|
23
|
+
};
|
|
24
|
+
var _fullViewingKey;
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.InMemoryViewingKey = void 0;
|
|
27
|
+
const utils_1 = require("@taquito/utils");
|
|
28
|
+
const sapling = require("@airgap/sapling-wasm");
|
|
29
|
+
const in_memory_spending_key_1 = require("./in-memory-spending-key");
|
|
30
|
+
/**
|
|
31
|
+
* @description Holds the viewing key
|
|
32
|
+
*/
|
|
33
|
+
class InMemoryViewingKey {
|
|
34
|
+
constructor(fullViewingKey) {
|
|
35
|
+
_fullViewingKey.set(this, void 0);
|
|
36
|
+
__classPrivateFieldSet(this, _fullViewingKey, Buffer.from(fullViewingKey, 'hex'));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* @description Allows to instantiate the InMemoryViewingKey from an encrypted/unencrypted spending key
|
|
40
|
+
*
|
|
41
|
+
* @param spendingKey Base58Check-encoded spending key
|
|
42
|
+
* @param password Optional password to decrypt the spending key
|
|
43
|
+
* @example
|
|
44
|
+
* ```
|
|
45
|
+
* await InMemoryViewingKey.fromSpendingKey('sask27SLmU9herddHz4qFJBLMjWYMbJF8RtS579w9ej9mfCYK7VUdyCJPHK8AzW9zMsopGZEkYeNjAY7Zz1bkM7CGu8eKLzrjBLTMC5wWJDhxiK91ahA29rhDRsHdJDV2u2jFwb2MNUix8JW7sAkAqYVaJpCehTBPgRQ1KqKwqqUaNmuD8kazd4Q8MCWmgbWs21Yuomdqyi9FLigjRp7oY4m5adaVU19Nj1AHvsMY2tePeU2L')
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
*/
|
|
49
|
+
static fromSpendingKey(spendingKey, password) {
|
|
50
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
+
const inMemorySpendingkey = new in_memory_spending_key_1.InMemorySpendingKey(spendingKey, password);
|
|
52
|
+
return inMemorySpendingkey.getSaplingViewingKeyProvider();
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* @description Retrieve the full viewing key
|
|
57
|
+
* @returns Buffer representing the full viewing key
|
|
58
|
+
*
|
|
59
|
+
*/
|
|
60
|
+
getFullViewingKey() {
|
|
61
|
+
return __classPrivateFieldGet(this, _fullViewingKey);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* @description Retrieve the outgoing viewing key
|
|
65
|
+
* @returns Buffer representing the outgoing viewing key
|
|
66
|
+
*
|
|
67
|
+
*/
|
|
68
|
+
getOutgoingViewingKey() {
|
|
69
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
70
|
+
return sapling.getOutgoingViewingKey(__classPrivateFieldGet(this, _fullViewingKey));
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* @description Retrieve the incoming viewing key
|
|
75
|
+
* @returns Buffer representing the incoming viewing key
|
|
76
|
+
*
|
|
77
|
+
*/
|
|
78
|
+
getIncomingViewingKey() {
|
|
79
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
80
|
+
return sapling.getIncomingViewingKey(__classPrivateFieldGet(this, _fullViewingKey));
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* @description Retrieve a payment address
|
|
85
|
+
* @param addressIndex used to determine which diversifier should be used to derive the address, default is 0
|
|
86
|
+
* @returns Base58Check-encoded address and its index
|
|
87
|
+
*
|
|
88
|
+
*/
|
|
89
|
+
getAddress(addressIndex) {
|
|
90
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
+
const { index, raw } = yield sapling.getPaymentAddressFromViewingKey(__classPrivateFieldGet(this, _fullViewingKey), addressIndex);
|
|
92
|
+
return {
|
|
93
|
+
address: utils_1.b58cencode(raw, utils_1.prefix[utils_1.Prefix.ZET1]),
|
|
94
|
+
addressIndex: index.readInt32LE(),
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.InMemoryViewingKey = InMemoryViewingKey;
|
|
100
|
+
_fullViewingKey = new WeakMap();
|
|
101
|
+
//# sourceMappingURL=in-memory-viewing-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory-viewing-key.js","sourceRoot":"","sources":["../../../src/sapling-keys/in-memory-viewing-key.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,0CAA4D;AAC5D,gDAAgD;AAChD,qEAA+D;AAE/D;;GAEG;AACH,MAAa,kBAAkB;IAE7B,YAAY,cAAsB;QADlC,kCAAwB;QAEtB,uBAAA,IAAI,mBAAmB,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC,EAAC;IAC5D,CAAC;IAED;;;;;;;;;;OAUG;IACH,MAAM,CAAO,eAAe,CAAC,WAAmB,EAAE,QAAiB;;YACjE,MAAM,mBAAmB,GAAG,IAAI,4CAAmB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;YAC3E,OAAO,mBAAmB,CAAC,4BAA4B,EAAE,CAAC;QAC5D,CAAC;KAAA;IAED;;;;OAIG;IACH,iBAAiB;QACf,qDAA4B;IAC9B,CAAC;IAED;;;;OAIG;IACG,qBAAqB;;YACzB,OAAO,OAAO,CAAC,qBAAqB,+CAAsB,CAAC;QAC7D,CAAC;KAAA;IAED;;;;OAIG;IACG,qBAAqB;;YACzB,OAAO,OAAO,CAAC,qBAAqB,+CAAsB,CAAC;QAC7D,CAAC;KAAA;IAED;;;;;OAKG;IACG,UAAU,CAAC,YAAqB;;YACpC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,MAAM,OAAO,CAAC,+BAA+B,gDAElE,YAAY,CACb,CAAC;YACF,OAAO;gBACL,OAAO,EAAE,kBAAU,CAAC,GAAG,EAAE,cAAM,CAAC,cAAM,CAAC,IAAI,CAAC,CAAC;gBAC7C,YAAY,EAAE,KAAK,CAAC,WAAW,EAAE;aAClC,CAAC;QACJ,CAAC;KAAA;CACF;AAjED,gDAiEC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SaplingWrapper = void 0;
|
|
13
|
+
const sapling = require("@airgap/sapling-wasm");
|
|
14
|
+
const random_1 = require("@stablelib/random");
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
16
|
+
const saplingOutputParams = require('../saplingOutputParams');
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
18
|
+
const saplingSpendParams = require('../saplingSpendParams');
|
|
19
|
+
class SaplingWrapper {
|
|
20
|
+
withProvingContext(action) {
|
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
yield this.initSaplingParameters();
|
|
23
|
+
return sapling.withProvingContext(action);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
getRandomBytes(length) {
|
|
27
|
+
return random_1.randomBytes(length);
|
|
28
|
+
}
|
|
29
|
+
randR() {
|
|
30
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
31
|
+
return sapling.randR();
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
getOutgoingViewingKey(vk) {
|
|
35
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
return sapling.getOutgoingViewingKey(vk);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
preparePartialOutputDescription(parametersOutputProof) {
|
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
const partialOutputDesc = yield sapling.preparePartialOutputDescription(parametersOutputProof.saplingContext, parametersOutputProof.address, parametersOutputProof.randomCommitmentTrapdoor, parametersOutputProof.ephemeralPrivateKey, parametersOutputProof.amount);
|
|
42
|
+
return {
|
|
43
|
+
commitmentValue: partialOutputDesc.cv,
|
|
44
|
+
commitment: partialOutputDesc.cm,
|
|
45
|
+
proof: partialOutputDesc.proof,
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
getDiversifiedFromRawPaymentAddress(decodedDestination) {
|
|
50
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
+
return sapling.getDiversifiedFromRawPaymentAddress(decodedDestination);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
deriveEphemeralPublicKey(diversifier, esk) {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
return sapling.deriveEphemeralPublicKey(diversifier, esk);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
getPkdFromRawPaymentAddress(destination) {
|
|
60
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
+
return sapling.getPkdFromRawPaymentAddress(destination);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
keyAgreement(p, sk) {
|
|
65
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
66
|
+
return sapling.keyAgreement(p, sk);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
createBindingSignature(saplingContext, balance, transactionSigHash) {
|
|
70
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
+
return sapling.createBindingSignature(saplingContext, balance, transactionSigHash);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
initSaplingParameters() {
|
|
75
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
76
|
+
const spendParams = Buffer.from(saplingSpendParams.saplingSpendParams, 'base64');
|
|
77
|
+
const outputParams = Buffer.from(saplingOutputParams.saplingOutputParams, 'base64');
|
|
78
|
+
return sapling.initParameters(spendParams, outputParams);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.SaplingWrapper = SaplingWrapper;
|
|
83
|
+
//# sourceMappingURL=sapling-module-wrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sapling-module-wrapper.js","sourceRoot":"","sources":["../../src/sapling-module-wrapper.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,gDAAgD;AAChD,8CAAgD;AAEhD,8DAA8D;AAC9D,MAAM,mBAAmB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;AAC9D,8DAA8D;AAC9D,MAAM,kBAAkB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;AAE5D,MAAa,cAAc;IACnB,kBAAkB,CAAI,MAAuC;;YACjE,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACnC,OAAO,OAAO,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;KAAA;IAED,cAAc,CAAC,MAAc;QAC3B,OAAO,oBAAW,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IAEK,KAAK;;YACT,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC;QACzB,CAAC;KAAA;IAEK,qBAAqB,CAAC,EAAU;;YACpC,OAAO,OAAO,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;QAC3C,CAAC;KAAA;IAEK,+BAA+B,CAAC,qBAA4C;;YAChF,MAAM,iBAAiB,GAAG,MAAM,OAAO,CAAC,+BAA+B,CACrE,qBAAqB,CAAC,cAAc,EACpC,qBAAqB,CAAC,OAAO,EAC7B,qBAAqB,CAAC,wBAAwB,EAC9C,qBAAqB,CAAC,mBAAmB,EACzC,qBAAqB,CAAC,MAAM,CAC7B,CAAC;YACF,OAAO;gBACL,eAAe,EAAE,iBAAiB,CAAC,EAAE;gBACrC,UAAU,EAAE,iBAAiB,CAAC,EAAE;gBAChC,KAAK,EAAE,iBAAiB,CAAC,KAAK;aAC/B,CAAC;QACJ,CAAC;KAAA;IAEK,mCAAmC,CAAC,kBAA8B;;YACtE,OAAO,OAAO,CAAC,mCAAmC,CAAC,kBAAkB,CAAC,CAAC;QACzE,CAAC;KAAA;IAEK,wBAAwB,CAAC,WAAmB,EAAE,GAAW;;YAC7D,OAAO,OAAO,CAAC,wBAAwB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QAC5D,CAAC;KAAA;IAEK,2BAA2B,CAAC,WAAuB;;YACvD,OAAO,OAAO,CAAC,2BAA2B,CAAC,WAAW,CAAC,CAAC;QAC1D,CAAC;KAAA;IAEK,YAAY,CAAC,CAAS,EAAE,EAAU;;YACtC,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACrC,CAAC;KAAA;IAEK,sBAAsB,CAC1B,cAAsB,EACtB,OAAe,EACf,kBAA8B;;YAE9B,OAAO,OAAO,CAAC,sBAAsB,CAAC,cAAc,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC;QACrF,CAAC;KAAA;IAEK,qBAAqB;;YACzB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;YACjF,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;YAEpF,OAAO,OAAO,CAAC,cAAc,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QAC3D,CAAC;KAAA;CACF;AA/DD,wCA+DC"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Some code in this file was originally written or inspired by Airgap-it
|
|
4
|
+
* https://github.com/airgap-it/airgap-coin-lib/blob/master/LICENSE.md
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
11
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
12
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
13
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.SaplingState = void 0;
|
|
18
|
+
const error_1 = require("../error");
|
|
19
|
+
const sapling_wasm_1 = require("@airgap/sapling-wasm");
|
|
20
|
+
const utils_1 = require("./utils");
|
|
21
|
+
const utils_2 = require("@taquito/utils");
|
|
22
|
+
const bignumber_js_1 = require("bignumber.js");
|
|
23
|
+
/**
|
|
24
|
+
* @description The SaplingState class's main purpose is to provide a Merkle path for the forger and the transaction builder, so that it may verify that the Sapling transaction is valid
|
|
25
|
+
*
|
|
26
|
+
*/
|
|
27
|
+
class SaplingState {
|
|
28
|
+
constructor(height) {
|
|
29
|
+
this.height = height;
|
|
30
|
+
this.uncommittedMerkleHash = '0100000000000000000000000000000000000000000000000000000000000000';
|
|
31
|
+
this.uncommittedMerkleHashes = new utils_1.Lazy(() => this.createUncommittedMerkleHashes());
|
|
32
|
+
}
|
|
33
|
+
getStateTree(stateDiff, constructTree = true) {
|
|
34
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
if (this.stateTree !== undefined && this.stateTree.root === stateDiff.root) {
|
|
36
|
+
return this.stateTree;
|
|
37
|
+
}
|
|
38
|
+
const commitments = stateDiff.commitments_and_ciphertexts.map(([commitment, _]) => commitment);
|
|
39
|
+
let merkleTree;
|
|
40
|
+
if (constructTree) {
|
|
41
|
+
merkleTree = yield this.constructMerkleTree(commitments, 0);
|
|
42
|
+
yield this.validateMerkleTree(merkleTree, stateDiff.root);
|
|
43
|
+
}
|
|
44
|
+
this.stateTree = {
|
|
45
|
+
height: this.height,
|
|
46
|
+
size: commitments.length,
|
|
47
|
+
root: stateDiff.root,
|
|
48
|
+
tree: merkleTree,
|
|
49
|
+
};
|
|
50
|
+
return this.stateTree;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
*
|
|
55
|
+
* @param stateTree stateTree parameter that holds information details on our Merkle tree
|
|
56
|
+
* @param position position of the hash in the Merkle tree
|
|
57
|
+
* @returns a promise of a string that serves as the Merkle path that can be passed on to the Sapling forger or the transaction builder
|
|
58
|
+
*/
|
|
59
|
+
getWitness(stateTree, position) {
|
|
60
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
+
const heightBuffer = utils_2.hex2Bytes(utils_1.changeEndianness(utils_2.num2PaddedHex(stateTree.height)));
|
|
62
|
+
const posBuffer = utils_2.hex2Bytes(utils_1.changeEndianness(utils_2.num2PaddedHex(position, 64)));
|
|
63
|
+
const neighbouringHashes = yield this.getNeighbouringHashes([], stateTree.height, position, stateTree.tree);
|
|
64
|
+
const witness = neighbouringHashes
|
|
65
|
+
.map((hash) => Buffer.concat([utils_2.hex2Bytes(utils_1.changeEndianness(utils_2.num2PaddedHex(hash.length))), hash]))
|
|
66
|
+
.reverse()
|
|
67
|
+
.reduce((acc, next) => Buffer.concat([acc, next]));
|
|
68
|
+
return Buffer.concat([heightBuffer, witness, posBuffer]).toString('hex');
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
*
|
|
73
|
+
* @param leaves array of leaves or nodes that we want to construct the Merkle tree from
|
|
74
|
+
* @param height height of the desired Merkle tree
|
|
75
|
+
* @returns a promise of MerkleTree type object
|
|
76
|
+
*/
|
|
77
|
+
constructMerkleTree(leaves, height) {
|
|
78
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
79
|
+
if (height === this.height && leaves.length === 1) {
|
|
80
|
+
return leaves[0];
|
|
81
|
+
}
|
|
82
|
+
if (height === this.height || leaves.length > Math.pow(2, this.height - 1 - height)) {
|
|
83
|
+
throw new error_1.TreeConstructionFailure('Children length exceeds maximum number of nodes in a merkle tree');
|
|
84
|
+
}
|
|
85
|
+
const pairedLeaves = utils_1.pairNodes(leaves);
|
|
86
|
+
const updatedLeaves = yield Promise.all(pairedLeaves.map((chunk) => __awaiter(this, void 0, void 0, function* () {
|
|
87
|
+
const left = yield this.getMerkleHash(chunk[0], height);
|
|
88
|
+
const right = yield this.getMerkleHash(chunk[1], height);
|
|
89
|
+
const parentHash = yield sapling_wasm_1.merkleHash(height, left, right);
|
|
90
|
+
return [parentHash.toString('hex'), chunk[0], chunk[1]];
|
|
91
|
+
})));
|
|
92
|
+
return this.constructMerkleTree(updatedLeaves, height + 1);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
getMerkleHash(tree, height) {
|
|
96
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
97
|
+
if (tree === undefined) {
|
|
98
|
+
return (yield this.uncommittedMerkleHashes.get())[height];
|
|
99
|
+
}
|
|
100
|
+
else if (typeof tree === 'string') {
|
|
101
|
+
return Buffer.from(tree, 'hex');
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
return Buffer.from(tree[0], 'hex');
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
*
|
|
110
|
+
* @returns hashes of empty or null values to fill in the Merkle tree
|
|
111
|
+
*/
|
|
112
|
+
createUncommittedMerkleHashes() {
|
|
113
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
114
|
+
const res = new Array(this.height);
|
|
115
|
+
res[0] = Buffer.from(this.uncommittedMerkleHash, 'hex');
|
|
116
|
+
for (let i = 0; i < this.height; i++) {
|
|
117
|
+
const hash = res[i];
|
|
118
|
+
res[i + 1] = yield sapling_wasm_1.merkleHash(i, hash, hash);
|
|
119
|
+
}
|
|
120
|
+
return res;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
*
|
|
125
|
+
* @param tree Merkle tree to validate
|
|
126
|
+
* @param expectedRoot the expected merkle root to validate against
|
|
127
|
+
*/
|
|
128
|
+
validateMerkleTree(tree, expectedRoot) {
|
|
129
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
130
|
+
const root = yield this.getMerkleHash(tree, this.height - 1);
|
|
131
|
+
if (root.toString('hex') !== expectedRoot) {
|
|
132
|
+
throw new error_1.InvalidMerkleRootError(root.toString('hex'));
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
*
|
|
138
|
+
* @param acc accumulator variable for the recursive function
|
|
139
|
+
* @param height height of the tree
|
|
140
|
+
* @param position position of the hash we would like find the neighbours of
|
|
141
|
+
* @param tree the Merkle tree that we want to traverse
|
|
142
|
+
* @returns the accumulated Buffer array of neighbouring hashes
|
|
143
|
+
*/
|
|
144
|
+
getNeighbouringHashes(acc, height, position, tree) {
|
|
145
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
146
|
+
if (typeof tree === 'undefined') {
|
|
147
|
+
throw new Error();
|
|
148
|
+
}
|
|
149
|
+
else if (typeof tree === 'string') {
|
|
150
|
+
return acc;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
let nextPos, nextTree, otherTree;
|
|
154
|
+
const fullTree = new bignumber_js_1.default(2).pow(height - 1);
|
|
155
|
+
if (position.lt(fullTree)) {
|
|
156
|
+
nextPos = position;
|
|
157
|
+
nextTree = tree[1];
|
|
158
|
+
otherTree = tree[2];
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
nextPos = position.minus(fullTree);
|
|
162
|
+
nextTree = tree[2];
|
|
163
|
+
otherTree = tree[1];
|
|
164
|
+
}
|
|
165
|
+
return this.getNeighbouringHashes([yield this.getMerkleHash(otherTree, height - 1), ...acc], height - 1, nextPos, nextTree);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
exports.SaplingState = SaplingState;
|
|
171
|
+
//# sourceMappingURL=sapling-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sapling-state.js","sourceRoot":"","sources":["../../../src/sapling-state/sapling-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.changeEndianness = exports.Lazy = exports.pairNodes = void 0;
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @param leaves nodes in the tree that we would like to make pairs from
|
|
16
|
+
* @returns a paired/chunked array: [a, b, c, d] => [[a, b], [c, d]]
|
|
17
|
+
*/
|
|
18
|
+
function pairNodes(leaves) {
|
|
19
|
+
const pairs = new Array(Math.ceil(leaves.length / 2));
|
|
20
|
+
for (let i = 0; i < leaves.length / 2; i++) {
|
|
21
|
+
pairs[i] = leaves.slice(i * 2, i * 2 + 2);
|
|
22
|
+
}
|
|
23
|
+
return pairs;
|
|
24
|
+
}
|
|
25
|
+
exports.pairNodes = pairNodes;
|
|
26
|
+
/**
|
|
27
|
+
* @description helper function to assist in Lazy initializing an object
|
|
28
|
+
*/
|
|
29
|
+
class Lazy {
|
|
30
|
+
constructor(init) {
|
|
31
|
+
this.init = init;
|
|
32
|
+
this.isInitialized = false;
|
|
33
|
+
this.value = undefined;
|
|
34
|
+
}
|
|
35
|
+
// initializes the lazily initiated object
|
|
36
|
+
get() {
|
|
37
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
38
|
+
if (!this.isInitialized) {
|
|
39
|
+
this.value = yield this.init();
|
|
40
|
+
this.isInitialized = true;
|
|
41
|
+
}
|
|
42
|
+
return this.value;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.Lazy = Lazy;
|
|
47
|
+
/**
|
|
48
|
+
*
|
|
49
|
+
* @param hex hexadecimal string we would like to swap
|
|
50
|
+
* @returns a hexadecimal string with swapped endians
|
|
51
|
+
*/
|
|
52
|
+
const changeEndianness = (hex) => {
|
|
53
|
+
if (hex.length % 2 != 0) {
|
|
54
|
+
hex = '0' + hex;
|
|
55
|
+
}
|
|
56
|
+
const bytes = hex.match(/.{2}/g) || [];
|
|
57
|
+
return bytes.reverse().join('');
|
|
58
|
+
};
|
|
59
|
+
exports.changeEndianness = changeEndianness;
|
|
60
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/sapling-state/utils.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA;;;;GAIG;AACH,SAAgB,SAAS,CAAI,MAAW;IACtC,MAAM,KAAK,GAAwB,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAE3E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;QAC1C,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;KAC3C;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AARD,8BAQC;AAED;;GAEG;AACH,MAAa,IAAI;IAKf,YAA6B,IAAsB;QAAtB,SAAI,GAAJ,IAAI,CAAkB;QAJ3C,kBAAa,GAAG,KAAK,CAAC;QAEtB,UAAK,GAAO,SAAS,CAAC;IAEwB,CAAC;IAEvD,0CAA0C;IAC7B,GAAG;;YACd,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;gBACvB,IAAI,CAAC,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC/B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;aAC3B;YAED,OAAO,IAAI,CAAC,KAAU,CAAC;QACzB,CAAC;KAAA;CACF;AAhBD,oBAgBC;AAED;;;;GAIG;AACI,MAAM,gBAAgB,GAAG,CAAC,GAAW,EAAU,EAAE;IACtD,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE;QACvB,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;KACjB;IACD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAEvC,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAClC,CAAC,CAAC;AAPW,QAAA,gBAAgB,oBAO3B"}
|