UNPKG

@desig/web3

Version:

Desig: The Blockchain-Agnostic Multisig Solution

178 lines 10.4 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Transaction = void 0; const core_1 = require("@desig/core"); const connection_1 = require("../connection"); const utils_1 = require("@noble/hashes/utils"); const sha3_1 = require("@noble/hashes/sha3"); const bs58_1 = require("bs58"); const types_1 = require("../types"); const supported_chains_1 = require("@desig/supported-chains"); const transaction_parser_1 = require("./transaction.parser"); class Transaction extends connection_1.Connection { constructor(cluster, privkey, keypair) { super(cluster, (0, bs58_1.decode)(privkey), keypair); this.watch = (callback) => { const multisigId = (0, bs58_1.encode)(this.keypair.masterkey); const unwatch = this.on(connection_1.EventStreaming.signature, multisigId, callback); return unwatch; }; this.getTransactions = ({ approved, size = 10, after, } = {}) => __awaiter(this, void 0, void 0, function* () { const params = { multisigId: (0, bs58_1.encode)(this.keypair.masterkey), size, after, }; if (typeof approved === 'boolean') params.approved = approved; const { data } = yield this.connection.get('/transaction', { params, }); return data; }); this.getTransaction = (transactionId) => __awaiter(this, void 0, void 0, function* () { const { data } = yield this.connection.get(`/transaction/${transactionId}`); return data; }); this.getSignature = (signatureId) => __awaiter(this, void 0, void 0, function* () { const { data } = yield this.connection.get(`/signature/${signatureId}`); return data; }); this.initializeTransaction = ({ type, params, ttl, }) => __awaiter(this, void 0, void 0, function* () { const payload = { multisigId: (0, bs58_1.encode)(this.keypair.masterkey), type, params, }; if (ttl) payload.ttl = ttl; const Authorization = yield this.getAuthorization(payload); const { data } = yield this.connection.post('/transaction', payload, { headers: { Authorization } }); return data; }); this.signTransaction = (transactionId) => __awaiter(this, void 0, void 0, function* () { const txParser = new transaction_parser_1.TransactionParser(); const elgamal = new core_1.ElGamal(); const { msg, raw, signatures } = yield this.getTransaction(transactionId); const { pullrequest } = signatures.find(({ signer: { id } }) => id === this.index); let sig = this.sign((0, bs58_1.decode)(this.index), (0, bs58_1.decode)(msg)); const tx = (0, bs58_1.decode)(raw); const { txType } = (yield txParser.verify(tx)) || {}; if (txType === types_1.TransactionType.nExtension) { const r = elgamal.decrypt((0, bs58_1.decode)(pullrequest).subarray(0, 64), this.privkey); const z = this.sss.ff.add(this.keypair.share, r); sig = (0, utils_1.concatBytes)(sig, z); } else if (txType === types_1.TransactionType.nReduction) { } else if (txType === types_1.TransactionType.tExtension) { } else if (txType === types_1.TransactionType.tReduction) { const r = elgamal.decrypt((0, bs58_1.decode)(pullrequest).subarray(0, 64), this.privkey); const z = this.sss.ff.add(this.keypair.share, r); sig = (0, utils_1.concatBytes)(sig, z); } else throw new Error('Invalid transaction type'); const signatureId = Transaction.deriveSignatureId(transactionId, this.index); const payload = { signature: (0, bs58_1.encode)(sig) }; const Authorization = yield this.getAuthorization(payload); const { data } = yield this.connection.patch(`/signature/${signatureId}`, payload, { headers: { Authorization } }); return data; }); this.execTransaction = (transactionId) => __awaiter(this, void 0, void 0, function* () { const { data } = yield this.connection.patch(`/transaction/${transactionId}`); return data; }); this.syncTransaction = () => __awaiter(this, void 0, void 0, function* () { const txParser = new transaction_parser_1.TransactionParser(); const extendedElgamal = new core_1.ExtendedElGamal(); const elgamal = new core_1.ElGamal(); const ff = this.sss.ff; const txs = yield this.getTransactions({ approved: true }); const currentGid = (0, bs58_1.encode)(this.keypair.id); let currentPos = -1; for (let i = 0; i < txs.length; i++) { const { raw } = txs[i]; const { refgid } = yield txParser.verify((0, bs58_1.decode)(raw)); if ((0, bs58_1.encode)(refgid) === currentGid) { currentPos = i; break; } } if (currentPos < 0) throw new Error('Corrupted chain data.'); const waitingTxs = txs.slice(0, currentPos + 1); while (waitingTxs.length) { const { id: transactionId, raw } = waitingTxs.pop(); const { signatures } = yield this.getTransaction(transactionId); const tx = (0, bs58_1.decode)(raw); const { txType, refgid, t, n } = yield txParser.verify(tx); const _t = ff.decode(ff.numberToRedBN(t), 8); const _n = ff.decode(ff.numberToRedBN(n), 8); const { pullrequest } = signatures.find(({ signer: { id } }) => id === this.index) || { pullrequest: (0, bs58_1.encode)(tx.subarray(72)) }; if (txType === types_1.TransactionType.nExtension) { const zero = elgamal.decrypt((0, bs58_1.decode)(pullrequest).subarray(64, 128), this.privkey); this.keypair.proactivate((0, utils_1.concatBytes)(this.keypair.index, _t, _n, (0, bs58_1.decode)(transactionId), zero)); } else if (txType === types_1.TransactionType.nReduction) { const zero = elgamal.decrypt((0, bs58_1.decode)(pullrequest), this.privkey); this.keypair.proactivate((0, utils_1.concatBytes)(this.keypair.index, _t, _n, (0, bs58_1.decode)(transactionId), zero)); } else if (txType === types_1.TransactionType.tExtension) { const zero = elgamal.decrypt((0, bs58_1.decode)(pullrequest), this.privkey); this.keypair.proactivate((0, utils_1.concatBytes)(this.keypair.index, _t, _n, (0, bs58_1.decode)(transactionId), zero)); } else if (txType === types_1.TransactionType.tReduction) { const zero = elgamal.decrypt((0, bs58_1.decode)(pullrequest).subarray(64, 128), this.privkey); const shares = signatures .filter(({ signature }) => !!signature) .map(({ signature, signer: { id } }) => [ (0, bs58_1.decode)(id), (0, bs58_1.decode)(signature), ]) .map(([id, signature]) => { const commitment = signature.subarray(64); return (0, utils_1.concatBytes)(id, ff.decode(ff.numberToRedBN(t).add(this.sss.ff.ONE), 8), _n, refgid, commitment); }); const z = this.sss.ff.neg(this.sss.ff.mul(this.sss.ft1(shares), this.sss.ff.pow(this.keypair.index, t))); this.keypair.proactivate((0, utils_1.concatBytes)(this.keypair.index, _t, _n, (0, bs58_1.decode)(transactionId), z)); this.keypair.proactivate((0, utils_1.concatBytes)(this.keypair.index, _t, _n, (0, bs58_1.decode)(transactionId), zero)); } else throw new Error('Unsupported Desig transaction.'); } const encryptedShare = (0, bs58_1.encode)(extendedElgamal.encrypt(new TextEncoder().encode(this.keypair.getSecretKey()), (0, bs58_1.decode)(this.owner))); const payload = { activated: true, encryptedShare }; const Authorization = yield this.getAuthorization(payload); const { data } = yield this.connection.patch(`/signer/${this.index}`, payload, { headers: { Authorization } }); return data; }); this.sss = (() => { switch (this.keypair.curve) { case supported_chains_1.Curve.ed25519: return new core_1.SecretSharing(core_1.EdCurve.ff); case supported_chains_1.Curve.secp256k1: return new core_1.SecretSharing(core_1.ECCurve.ff); default: throw new Error('Unsupported elliptic curve.'); } })(); } static deriveSignatureId(transactionId, signerId) { const seed = (0, utils_1.concatBytes)((0, bs58_1.decode)(transactionId), (0, bs58_1.decode)(signerId)); return (0, bs58_1.encode)((0, sha3_1.keccak_256)(seed)); } } exports.Transaction = Transaction; Transaction.deriveTransactionId = (msg) => (0, bs58_1.encode)((0, bs58_1.decode)(msg).subarray(0, 8)); //# sourceMappingURL=index.js.map