@gandlaf21/bc-ur
Version:
A JS implementation of the Uniform Resources (UR) specification from Blockchain Commons
138 lines • 6.27 kB
JavaScript
import { bufferXOR, getCRC, split, toUint32 } from "./utils";
import { chooseFragments } from "./fountainUtils";
import { cborEncode, cborDecode } from './cbor';
import { Buffer } from "buffer";
var FountainEncoderPart = /** @class */ (function () {
function FountainEncoderPart(_seqNum, _seqLength, _messageLength, _checksum, _fragment) {
this._seqNum = _seqNum;
this._seqLength = _seqLength;
this._messageLength = _messageLength;
this._checksum = _checksum;
this._fragment = _fragment;
}
Object.defineProperty(FountainEncoderPart.prototype, "messageLength", {
get: function () { return this._messageLength; },
enumerable: false,
configurable: true
});
Object.defineProperty(FountainEncoderPart.prototype, "fragment", {
get: function () { return this._fragment; },
enumerable: false,
configurable: true
});
Object.defineProperty(FountainEncoderPart.prototype, "seqNum", {
get: function () { return this._seqNum; },
enumerable: false,
configurable: true
});
Object.defineProperty(FountainEncoderPart.prototype, "seqLength", {
get: function () { return this._seqLength; },
enumerable: false,
configurable: true
});
Object.defineProperty(FountainEncoderPart.prototype, "checksum", {
get: function () { return this._checksum; },
enumerable: false,
configurable: true
});
FountainEncoderPart.prototype.cbor = function () {
var result = cborEncode([
this._seqNum,
this._seqLength,
this._messageLength,
this._checksum,
this._fragment
]);
return Buffer.from(result);
};
FountainEncoderPart.prototype.description = function () {
return "seqNum:" + this._seqNum + ", seqLen:" + this._seqLength + ", messageLen:" + this._messageLength + ", checksum:" + this._checksum + ", data:" + this._fragment.toString('hex');
};
FountainEncoderPart.fromCBOR = function (cborPayload) {
var _a = cborDecode(cborPayload), seqNum = _a[0], seqLength = _a[1], messageLength = _a[2], checksum = _a[3], fragment = _a[4];
if (typeof seqNum !== 'number' || typeof seqLength !== 'number' || typeof messageLength !== 'number' || typeof checksum !== 'number' || Buffer.isBuffer(fragment) && fragment.length <= 0) {
throw new Error("type error");
}
return new FountainEncoderPart(seqNum, seqLength, messageLength, checksum, Buffer.from(fragment));
};
return FountainEncoderPart;
}());
export { FountainEncoderPart };
var FountainEncoder = /** @class */ (function () {
function FountainEncoder(message, maxFragmentLength, firstSeqNum, minFragmentLength) {
if (maxFragmentLength === void 0) { maxFragmentLength = 100; }
if (firstSeqNum === void 0) { firstSeqNum = 0; }
if (minFragmentLength === void 0) { minFragmentLength = 10; }
var fragmentLength = FountainEncoder.findNominalFragmentLength(message.length, minFragmentLength, maxFragmentLength);
this._messageLength = message.length;
this._fragments = FountainEncoder.partitionMessage(message, fragmentLength);
this.fragmentLength = fragmentLength;
this.seqNum = toUint32(firstSeqNum);
this.checksum = getCRC(message);
}
Object.defineProperty(FountainEncoder.prototype, "fragmentsLength", {
get: function () { return this._fragments.length; },
enumerable: false,
configurable: true
});
Object.defineProperty(FountainEncoder.prototype, "fragments", {
get: function () { return this._fragments; },
enumerable: false,
configurable: true
});
Object.defineProperty(FountainEncoder.prototype, "messageLength", {
get: function () { return this._messageLength; },
enumerable: false,
configurable: true
});
FountainEncoder.prototype.isComplete = function () {
return this.seqNum >= this._fragments.length;
};
FountainEncoder.prototype.isSinglePart = function () {
return this._fragments.length === 1;
};
FountainEncoder.prototype.seqLength = function () {
return this._fragments.length;
};
FountainEncoder.prototype.mix = function (indexes) {
var _this = this;
return indexes.reduce(function (result, index) { return bufferXOR(_this._fragments[index], result); }, Buffer.alloc(this.fragmentLength, 0));
};
FountainEncoder.prototype.nextPart = function () {
this.seqNum = toUint32(this.seqNum + 1);
var indexes = chooseFragments(this.seqNum, this._fragments.length, this.checksum);
var mixed = this.mix(indexes);
return new FountainEncoderPart(this.seqNum, this._fragments.length, this._messageLength, this.checksum, mixed);
};
FountainEncoder.findNominalFragmentLength = function (messageLength, minFragmentLength, maxFragmentLength) {
if (messageLength <= 0 || minFragmentLength <= 0 || maxFragmentLength < minFragmentLength) {
throw new Error("invalid fragment or message length");
}
var maxFragmentCount = Math.ceil(messageLength / minFragmentLength);
var fragmentLength = 0;
for (var fragmentCount = 1; fragmentCount <= maxFragmentCount; fragmentCount++) {
fragmentLength = Math.ceil(messageLength / fragmentCount);
if (fragmentLength <= maxFragmentLength) {
break;
}
}
return fragmentLength;
};
FountainEncoder.partitionMessage = function (message, fragmentLength) {
var _a;
var remaining = Buffer.from(message);
var fragment;
var _fragments = [];
while (remaining.length > 0) {
_a = split(remaining, -fragmentLength), fragment = _a[0], remaining = _a[1];
fragment = Buffer
.alloc(fragmentLength, 0) // initialize with 0's to achieve the padding
.fill(fragment, 0, fragment.length);
_fragments.push(fragment);
}
return _fragments;
};
return FountainEncoder;
}());
export default FountainEncoder;
//# sourceMappingURL=fountainEncoder.js.map