219 lines
6.4 KiB
JavaScript
219 lines
6.4 KiB
JavaScript
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var $ = require('../util/preconditions');
|
|
var BN = require('../crypto/bn');
|
|
var buffer = require('buffer');
|
|
var BufferWriter = require('../encoding/bufferwriter');
|
|
var BufferUtil = require('../util/buffer');
|
|
var JSUtil = require('../util/js');
|
|
|
|
// TODO: Update ZCProof for Groth
|
|
//var ZCProof = require('../zcash/proof');
|
|
|
|
var ZC_NUM_JS_INPUTS = 2;
|
|
var ZC_NUM_JS_OUTPUTS = 2;
|
|
|
|
// leading + v + rho + r + memo + auth
|
|
var ZC_NOTECIPHERTEXT_SIZE = 1 + 8 + 32 + 32 + 512 + 16;
|
|
|
|
function JSDescription(params) {
|
|
if (!(this instanceof JSDescription)) {
|
|
return new JSDescription(params);
|
|
}
|
|
this.nullifiers = [];
|
|
this.commitments = [];
|
|
this.ciphertexts = [];
|
|
this.macs = [];
|
|
if (params) {
|
|
return this._fromObject(params);
|
|
}
|
|
}
|
|
|
|
Object.defineProperty(JSDescription.prototype, 'vpub_old', {
|
|
configurable: false,
|
|
enumerable: true,
|
|
get: function() {
|
|
return this._vpub_old;
|
|
},
|
|
set: function(num) {
|
|
if (num instanceof BN) {
|
|
this._vpub_oldBN = num;
|
|
this._vpub_old = num.toNumber();
|
|
} else if (_.isString(num)) {
|
|
this._vpub_old = parseInt(num);
|
|
this._vpub_oldBN = BN.fromNumber(this._vpub_old);
|
|
} else {
|
|
$.checkArgument(
|
|
JSUtil.isNaturalNumber(num),
|
|
'vpub_old is not a natural number'
|
|
);
|
|
this._vpub_oldBN = BN.fromNumber(num);
|
|
this._vpub_old = num;
|
|
}
|
|
$.checkState(
|
|
JSUtil.isNaturalNumber(this._vpub_old),
|
|
'vpub_old is not a natural number'
|
|
);
|
|
}
|
|
});
|
|
|
|
Object.defineProperty(JSDescription.prototype, 'vpub_new', {
|
|
configurable: false,
|
|
enumerable: true,
|
|
get: function() {
|
|
return this._vpub_new;
|
|
},
|
|
set: function(num) {
|
|
if (num instanceof BN) {
|
|
this._vpub_newBN = num;
|
|
this._vpub_new = num.toNumber();
|
|
} else if (_.isString(num)) {
|
|
this._vpub_new = parseInt(num);
|
|
this._vpub_newBN = BN.fromNumber(this._vpub_new);
|
|
} else {
|
|
$.checkArgument(
|
|
JSUtil.isNaturalNumber(num),
|
|
'vpub_new is not a natural number'
|
|
);
|
|
this._vpub_newBN = BN.fromNumber(num);
|
|
this._vpub_new = num;
|
|
}
|
|
$.checkState(
|
|
JSUtil.isNaturalNumber(this._vpub_new),
|
|
'vpub_new is not a natural number'
|
|
);
|
|
}
|
|
});
|
|
|
|
JSDescription.fromObject = function(obj) {
|
|
$.checkArgument(_.isObject(obj));
|
|
var jsdesc = new JSDescription();
|
|
return jsdesc._fromObject(obj);
|
|
};
|
|
|
|
JSDescription.prototype._fromObject = function(params) {
|
|
var nullifiers = [];
|
|
_.each(params.nullifiers, function(nullifier) {
|
|
nullifiers.push(BufferUtil.reverse(new buffer.Buffer(nullifier, 'hex')));
|
|
});
|
|
var commitments = [];
|
|
_.each(params.commitments, function(commitment) {
|
|
commitments.push(BufferUtil.reverse(new buffer.Buffer(commitment, 'hex')));
|
|
});
|
|
var ciphertexts = [];
|
|
_.each(params.ciphertexts, function(ciphertext) {
|
|
ciphertexts.push(new buffer.Buffer(ciphertext, 'hex'));
|
|
});
|
|
var macs = [];
|
|
_.each(params.macs, function(mac) {
|
|
macs.push(BufferUtil.reverse(new buffer.Buffer(mac, 'hex')));
|
|
});
|
|
this.vpub_old = params.vpub_old;
|
|
this.vpub_new = params.vpub_new;
|
|
this.anchor = BufferUtil.reverse(new buffer.Buffer(params.anchor, 'hex'));
|
|
this.nullifiers = nullifiers;
|
|
this.commitments = commitments;
|
|
this.ephemeralKey = BufferUtil.reverse(new buffer.Buffer(params.ephemeralKey, 'hex'));
|
|
this.ciphertexts = ciphertexts;
|
|
this.randomSeed = BufferUtil.reverse(new buffer.Buffer(params.randomSeed, 'hex'));
|
|
this.macs = macs;
|
|
this.proof = params.proof; // TODO: Update ZCProof for Groth: ZCProof.fromObject(params.proof);
|
|
return this;
|
|
};
|
|
|
|
JSDescription.prototype.toObject = JSDescription.prototype.toJSON = function toObject() {
|
|
var nullifiers = [];
|
|
_.each(this.nullifiers, function(nullifier) {
|
|
nullifiers.push(BufferUtil.reverse(nullifier).toString('hex'));
|
|
});
|
|
var commitments = [];
|
|
_.each(this.commitments, function(commitment) {
|
|
commitments.push(BufferUtil.reverse(commitment).toString('hex'));
|
|
});
|
|
var ciphertexts = [];
|
|
_.each(this.ciphertexts, function(ciphertext) {
|
|
ciphertexts.push(ciphertext.toString('hex'));
|
|
});
|
|
var macs = [];
|
|
_.each(this.macs, function(mac) {
|
|
macs.push(BufferUtil.reverse(mac).toString('hex'));
|
|
});
|
|
var obj = {
|
|
vpub_old: this.vpub_old,
|
|
vpub_new: this.vpub_new,
|
|
anchor: BufferUtil.reverse(this.anchor).toString('hex'),
|
|
nullifiers: nullifiers,
|
|
commitments: commitments,
|
|
ephemeralKey: BufferUtil.reverse(this.ephemeralKey).toString('hex'),
|
|
ciphertexts: ciphertexts,
|
|
randomSeed: BufferUtil.reverse(this.randomSeed).toString('hex'),
|
|
macs: macs,
|
|
proof: this.proof, // TODO: Update ZCProof for Groth: this.proof.toObject(),
|
|
};
|
|
return obj;
|
|
};
|
|
|
|
JSDescription.fromBufferReader = function(br, useGrothFlagParam) {
|
|
var i;
|
|
var jsdesc = new JSDescription();
|
|
jsdesc.vpub_old = br.readUInt64LEBN();
|
|
jsdesc.vpub_new = br.readUInt64LEBN();
|
|
jsdesc.anchor = br.read(32);
|
|
for (i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
|
jsdesc.nullifiers.push(br.read(32));
|
|
}
|
|
for (i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
|
jsdesc.commitments.push(br.read(32));
|
|
}
|
|
jsdesc.ephemeralKey = br.read(32);
|
|
jsdesc.randomSeed = br.read(32);
|
|
for (i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
|
jsdesc.macs.push(br.read(32));
|
|
}
|
|
|
|
// Default parameter requires ECMASCript 6 which might not be available, so use workaround.
|
|
var useGrothFlag = useGrothFlagParam || false;
|
|
if (!useGrothFlag) {
|
|
jsdesc.proof = br.read(296); // TODO: Update ZCProof for Groth: ZCProof.fromBufferReader(br);
|
|
} else {
|
|
jsdesc.proof = br.read(48 + 96 + 48);
|
|
}
|
|
|
|
for (i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
|
jsdesc.ciphertexts.push(br.read(ZC_NOTECIPHERTEXT_SIZE));
|
|
}
|
|
return jsdesc;
|
|
};
|
|
|
|
JSDescription.prototype.toBufferWriter = function(writer) {
|
|
var i;
|
|
if (!writer) {
|
|
writer = new BufferWriter();
|
|
}
|
|
writer.writeUInt64LEBN(this._vpub_oldBN);
|
|
writer.writeUInt64LEBN(this._vpub_newBN);
|
|
writer.write(this.anchor);
|
|
for (i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
|
writer.write(this.nullifiers[i]);
|
|
}
|
|
for (i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
|
writer.write(this.commitments[i]);
|
|
}
|
|
writer.write(this.ephemeralKey);
|
|
writer.write(this.randomSeed);
|
|
for (i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
|
writer.write(this.macs[i]);
|
|
}
|
|
|
|
// TODO: Update ZCProof for Groth: this.proof.toBufferWriter(writer);
|
|
writer.write(this.proof);
|
|
|
|
for (i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
|
writer.write(this.ciphertexts[i]);
|
|
}
|
|
return writer;
|
|
};
|
|
|
|
module.exports = JSDescription;
|