AccountIndex encoding updates via util/keyring (#281)

* AccountIndex encoding updates via util/keyring

* Proper ss58 AccountIndex decoding from keyring

* Metadata allows both length and non-length prefixed

* Update doc logo size & relative URL
This commit is contained in:
Jaco Greeff
2018-10-13 17:33:40 +02:00
committed by GitHub
parent 75e800374f
commit 7bc8386806
12 changed files with 103 additions and 57 deletions
+2 -2
View File
@@ -30,7 +30,7 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/types#readme",
"dependencies": {
"@babel/runtime": "^7.0.0",
"@polkadot/keyring": "^0.31.1",
"@polkadot/util": "^0.31.1"
"@polkadot/keyring": "^0.31.3",
"@polkadot/util": "^0.31.3"
}
}
+44 -20
View File
@@ -2,9 +2,12 @@
// This software may be modified and distributed under the terms
// of the ISC license. See the LICENSE file for details.
import decodeAddress from '@polkadot/keyring/address/decode';
import encodeAddress from '@polkadot/keyring/address/encode';
import hexToU8a from '@polkadot/util/hex/toU8a';
import isU8a from '@polkadot/util/is/u8a';
import u8aToHex from '@polkadot/util/u8a/toHex';
import u8aToU8a from '@polkadot/util/u8a/toU8a';
import isHex from '@polkadot/util/is/hex';
import u8aConcat from '@polkadot/util/u8a/concat';
import { AnyU8a } from './types';
import U8a from './codec/U8a';
@@ -19,41 +22,53 @@ export default class AccountIndex extends U8a {
);
}
// FIXME Not 100% sure how to handle the encoding of short addresses. It is (mostly)
// unused atm, options are to go to hex or to utf8. Here we go the hex route.
static encode (value: Uint8Array): string {
return u8aToHex(value);
}
static decodeAccountIndex (value: AnyU8a): Uint8Array {
if (value instanceof U8a) {
return value.raw;
} else if (Array.isArray(value)) {
return AccountIndex.decodeAccountIndex(Uint8Array.from(value));
} else if (isU8a(value)) {
if (!value.length) {
return value;
}
return value.subarray(0, AccountIndex.readLength(value));
const [offset, length] = AccountIndex.readLength(value);
return value.subarray(offset, offset + length);
} else if (isHex(value)) {
return hexToU8a(value);
}
return u8aToU8a(value);
return decodeAddress(value);
}
// TODO Double check the +1 with actual e2e data
static readLength (input: Uint8Array): number {
static readLength (input: Uint8Array): [number, number] {
const first = input[0];
if (first <= 0xef) {
return 1;
return [0, 1];
} else if (first === 0xfc) {
return 2 + 1;
return [1, 2];
} else if (first === 0xfd) {
return 4 + 1;
return [1, 4];
} else if (first === 0xfe) {
return 8 + 1;
return [1, 8];
}
throw new Error(`Invalid account index byte, 0x${first.toString(16)}`);
}
static writeLength (input: Uint8Array): Uint8Array {
switch (input.length) {
case 1: return new Uint8Array([]);
case 2: return new Uint8Array([0xfc]);
case 4: return new Uint8Array([0xfd]);
case 8: return new Uint8Array([0xfe]);
}
throw new Error(`Invalid account index length, ${input.length}`);
}
fromJSON (input: any): AccountIndex {
super.fromJSON(AccountIndex.decodeAccountIndex(input));
@@ -61,9 +76,9 @@ export default class AccountIndex extends U8a {
}
fromU8a (input: Uint8Array): AccountIndex {
super.fromU8a(
input.subarray(0, AccountIndex.readLength(input))
);
const [offset, length] = AccountIndex.readLength(input);
super.fromU8a(input.subarray(offset, offset + length));
return this;
}
@@ -72,7 +87,16 @@ export default class AccountIndex extends U8a {
return this.toString();
}
toU8a (isBare?: boolean): Uint8Array {
return isBare
? this.raw
: u8aConcat(
AccountIndex.writeLength(this.raw),
this.raw
);
}
toString (): string {
return AccountIndex.encode(this.raw);
return encodeAddress(this.raw);
}
}
+8 -8
View File
@@ -31,8 +31,8 @@ describe('Address', () => {
);
testDecode(
'AccountIndex',
new AccountIndex('0x0102030405060708010203040506070801020304050607080102030405060708'),
'0x0102030405060708010203040506070801020304050607080102030405060708'
new AccountIndex('0x0001'),
'25GUyk'
);
testDecode(
'Array',
@@ -54,23 +54,23 @@ describe('Address', () => {
);
testDecode(
'Uint8Array (with prefix 1 byte)',
Uint8Array.from([17]),
'0x11'
Uint8Array.from([1]),
'F7L6'
);
testDecode(
'Uint8Array (with prefix 2 bytes)',
Uint8Array.from([0xfc, 17, 18]),
'0xfc1112'
Uint8Array.from([0xfc, 0, 1]),
'25GUyk'
);
testDecode(
'Uint8Array (with prefix 4 bytes)',
Uint8Array.from([0xfd, 17, 18, 19, 20]),
'0xfd11121314'
'Mwz15xN8'
);
testDecode(
'Uint8Array (with prefix 8 bytes)',
Uint8Array.from([0xfe, 17, 18, 19, 20, 21, 22, 23, 24]),
'0xfe1112131415161718'
'3N5RJXxM5fLd4h'
);
// FIXME Add this
+10 -1
View File
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the ISC license. See the LICENSE file for details.
import hexToU8a from '@polkadot/util/hex/toU8a';
import Metadata from './Metadata';
import rpcdata from './Metadata.rpc';
@@ -13,6 +15,13 @@ describe('Metadata', () => {
console.error(str);
console.error(decoded.getUniqTypes());
expect(str).not.toBe(null);
expect(decoded.events.length).not.toBe(0);
});
it('decodes when length not present (HACK)', () => {
const u8a = hexToU8a(rpcdata);
const decoded = new Metadata().fromU8a(u8a.subarray(2));
expect(decoded.events.length).not.toBe(0);
});
});
+11 -3
View File
@@ -336,10 +336,18 @@ export default class RuntimeMetadata extends Struct {
}
fromU8a (input: Uint8Array): RuntimeMetadata {
// this does not look correct, metadata now has a length prefix. Strip, move on.
const [offset] = Compact.decodeU8a(input, DEFAULT_LENGTH_BITS);
// HACK 13 Oct 2018 - For current running BBQ nodes, Metadata is not properly
// encoded, it does not have a length prefix. For latest substrate master, it
// is properly encoded. Here we pull the prefix, check it agianst the length -
// if matches, then we have the length, otherwise we assume it is an older node
// and use the whole buffer
const [offset, length] = Compact.decodeU8a(input, DEFAULT_LENGTH_BITS);
super.fromU8a(input.subarray(offset));
super.fromU8a(
input.length === (offset + length.toNumber())
? input.subarray(offset)
: input
);
return this;
}