From 0c8547d49cd525337cd3f45b376c91cafe53156f Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Fri, 21 Dec 2018 15:15:59 +0100 Subject: [PATCH] Add tests from Rust (#283) * Add tests from Rust * Fix compact encoding --- packages/util/src/compact/toU8a.spec.ts | 35 +++++++++++++++++++++++++ packages/util/src/compact/toU8a.ts | 12 ++++++--- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/packages/util/src/compact/toU8a.spec.ts b/packages/util/src/compact/toU8a.spec.ts index 8d6237302..ed194bdfa 100644 --- a/packages/util/src/compact/toU8a.spec.ts +++ b/packages/util/src/compact/toU8a.spec.ts @@ -64,4 +64,39 @@ describe('encode', () => { new Uint8Array([3 + ((6 - 4) << 2), 0x00, 0x40, 0x7a, 0x10, 0xf3, 0x5a]) ); }); + + describe('from Rust', () => { + // Copied from https://github.com/paritytech/parity-codec/blob/master/src/codec.rs + const testCases = [ + { value: new BN('0'), expected: '00' }, + { value: new BN('63'), expected: 'fc' }, + { value: new BN('64'), expected: '01 01' }, + { value: new BN('16383'), expected: 'fd ff' }, + { value: new BN('16384'), expected: '02 00 01 00' }, + { value: new BN('1073741823'), expected: 'fe ff ff ff' }, + { value: new BN('1073741824'), expected: '03 00 00 00 40' }, + { value: new BN(`${1}${'0'.repeat(32)}`, 2).subn(1), expected: '03 ff ff ff ff' }, + { value: new BN(`${1}${'0'.repeat(32)}`, 2), expected: '07 00 00 00 00 01' }, + { value: new BN(`${1}${'0'.repeat(40)}`, 2), expected: '0b 00 00 00 00 00 01' }, + { value: new BN(`${1}${'0'.repeat(48)}`, 2), expected: '0f 00 00 00 00 00 00 01' }, + { value: new BN(`${1}${'0'.repeat(56)}`, 2).subn(1), expected: '0f ff ff ff ff ff ff ff' }, + { value: new BN(`${1}${'0'.repeat(56)}`, 2), expected: '13 00 00 00 00 00 00 00 01' }, + { value: new BN(`${1}${'0'.repeat(64)}`, 2).subn(1), expected: '13 ff ff ff ff ff ff ff ff' } + ]; + + function testEncode (value: BN, expected: string) { + it(`encodes ${value.toString()}`, () => { + expect( + compactToU8a(value) + ).toEqual( + Uint8Array.from( + expected.split(' ').map(s => parseInt(s, 16)) + ) + ); + }); + } + + testCases.forEach((({ value, expected }) => testEncode(value, expected))); + }); + }); diff --git a/packages/util/src/compact/toU8a.ts b/packages/util/src/compact/toU8a.ts index ad023c71d..89c106b36 100644 --- a/packages/util/src/compact/toU8a.ts +++ b/packages/util/src/compact/toU8a.ts @@ -4,6 +4,7 @@ import BN from 'bn.js'; +import assert from '../assert'; import { bnToBn, bnToU8a } from '../bn'; import { u8aConcat } from '../u8a'; @@ -34,16 +35,19 @@ export default function compactToU8a (_value: BN | number): Uint8Array { return bnToU8a(value.shln(2).addn(0b10), 32, true); } - const bitLength = value.bitLength(); + // Number of bytes needed to represent `value` + const bytesNeeded = Math.ceil(value.bitLength() / 8); + + assert(bytesNeeded >= 4, 'Previous tests match anyting less than 2^30; qed'); return u8aConcat( new Uint8Array([ - new BN(Math.ceil(bitLength / 8)) - .subn(4) // 4 bytes as a base + new BN(bytesNeeded) + .subn(4) // how many bytes more than 4 do we need? .shln(2) // clear low .addn(0b11) // add flag .toNumber() ]), - bnToU8a(value, bitLength, true) + bnToU8a(value) ); }