UNPKG

@gandlaf21/bc-ur

Version:

A JS implementation of the Uniform Resources (UR) specification from Blockchain Commons

46 lines (37 loc) 1.54 kB
import { intToBytes } from "./utils"; import Xoshiro from "./xoshiro"; // @ts-ignore import randomSampler from '@apocentre/alias-sampling' import { Buffer } from "buffer"; export const chooseDegree = (seqLenth: number, rng: Xoshiro): number => { const degreeProbabilities = [...new Array(seqLenth)].map((_, index) => 1 / (index + 1)); const degreeChooser = randomSampler(degreeProbabilities, null, rng.nextDouble); return degreeChooser.next() + 1; } export const shuffle = (items: any[], rng: Xoshiro): any[] => { let remaining = [...items]; let result = []; while (remaining.length > 0) { let index = rng.nextInt(0, remaining.length - 1); let item = remaining[index]; // remaining.erase(remaining.begin() + index); remaining.splice(index, 1); result.push(item); } return result; } export const chooseFragments = (seqNum: number, seqLength: number, checksum: number): number[] => { // The first `seqLenth` parts are the "pure" fragments, not mixed with any // others. This means that if you only generate the first `seqLenth` parts, // then you have all the parts you need to decode the message. if (seqNum <= seqLength) { return [seqNum - 1]; } else { const seed = Buffer.concat([intToBytes(seqNum), intToBytes(checksum)]); const rng = new Xoshiro(seed); const degree = chooseDegree(seqLength, rng); const indexes = [...new Array(seqLength)].map((_, index) => index); const shuffledIndexes = shuffle(indexes, rng); return shuffledIndexes.slice(0, degree); } }