Allow blake2 & parity-codec in trie (#251)
* Start codec implementation * Expose all constants * NodeHeader encoding/decoding * Encoding in NodeHeader * Constants for Node types * Moce codec to trie-codec * Encode/decode in place (untested) * WIP, tests starting to be put in place * One passing test :) * Another test bites the dust... * One more test down... * One more down * Additional tests * Formatting * Long keys passing * Trie tests * Follow the script, no all-in-all encoder * First simple trie test passing * Another one down * Extra checks remove (debug) * 80% there with tests... * One more, one left * Trie tests passing * ISC -> Apache-2.0 * Add compact util functions * Tests to TypeScript * Remove @polkadot/types deps, ethereum stub * Bump * Genesis tests with chainspecs * Cleanup tests (ease of debugging) * Substrate test passes, branch fails (again) * Checks passing, tests passing * Re-add Ethereum & snapshot tests (not passing atm) * Re-add index test (also not 100%) * Mid-way in generic trie-root * Cleanup ethereumjs-testing definitions * Update deps * Less intrusive renames in trie-hash * Self-review cleanups #1 * asNibbles -> toNibbles * Cleanups * Expand tests * Cleanup imports * Fix logger test (fly-by refactor) * Update snapshot test
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
// Copyright 2017-2018 @polkadot/trie-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { compactAddLength, u8aConcat, isU8a, logger } from '@polkadot/util/index';
|
||||
|
||||
import NodeHeader from './NodeHeader';
|
||||
import { NODE_TYPE_BRANCH, NODE_TYPE_EXT, NODE_TYPE_LEAF, NODE_TYPE_NULL } from './constants';
|
||||
import { extractKey } from './nibbles';
|
||||
import { fromNibbles } from './util';
|
||||
|
||||
const EMPTY = new Uint8Array();
|
||||
const BRANCH_VALUE_INDEX = 16;
|
||||
|
||||
const l = logger('trie/codec');
|
||||
|
||||
l.noop();
|
||||
|
||||
// in the case of odd nibbles, the first byte is encoded as a single
|
||||
// byte from the nibble, with the remainder of the nibbles is converted
|
||||
// as nomral nibble combined bytes
|
||||
function encodeKey (input: null | Uint8Array): Uint8Array {
|
||||
const nibbles = extractKey(input);
|
||||
|
||||
// l.debug(() => ['encodeKey', { input, nibbles }]);
|
||||
|
||||
return nibbles.length % 2
|
||||
? u8aConcat(
|
||||
Uint8Array.from([nibbles[0]]),
|
||||
fromNibbles(nibbles.subarray(1))
|
||||
)
|
||||
: fromNibbles(nibbles);
|
||||
}
|
||||
|
||||
function encodeValue (input: null | Uint8Array | Array<null | Uint8Array>): Uint8Array {
|
||||
if (!input) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
const encoded = encode(input);
|
||||
|
||||
// l.debug(() => ['encodeValue', { input, encoded }]);
|
||||
|
||||
return compactAddLength(encoded);
|
||||
}
|
||||
|
||||
function _encode (input?: null | Uint8Array | Array<null | Uint8Array>): Uint8Array {
|
||||
if (isU8a(input)) {
|
||||
return input;
|
||||
}
|
||||
|
||||
const header = new NodeHeader(input);
|
||||
const nodeType = header.nodeType;
|
||||
const u8aHeader = header.toU8a();
|
||||
|
||||
if (!input || nodeType === NODE_TYPE_NULL) {
|
||||
return u8aHeader;
|
||||
} else if (nodeType === NODE_TYPE_BRANCH) {
|
||||
let valuesU8a = EMPTY;
|
||||
let bitmap = 0;
|
||||
|
||||
input.reduce((cursor, value, index) => {
|
||||
if ((index < BRANCH_VALUE_INDEX) && value) {
|
||||
bitmap = bitmap | cursor;
|
||||
|
||||
valuesU8a = u8aConcat(
|
||||
valuesU8a,
|
||||
encodeValue(value)
|
||||
);
|
||||
}
|
||||
|
||||
return cursor << 1;
|
||||
}, 1);
|
||||
|
||||
return u8aConcat(
|
||||
u8aHeader,
|
||||
new Uint8Array([(bitmap % 256), Math.floor(bitmap / 256)]),
|
||||
encodeValue(input[BRANCH_VALUE_INDEX]),
|
||||
valuesU8a
|
||||
);
|
||||
} else if (nodeType === NODE_TYPE_EXT || nodeType === NODE_TYPE_LEAF) {
|
||||
const [key, value] = input;
|
||||
|
||||
return u8aConcat(
|
||||
u8aHeader,
|
||||
encodeKey(key),
|
||||
encodeValue(value)
|
||||
);
|
||||
}
|
||||
|
||||
throw new Error('Unreachable');
|
||||
}
|
||||
|
||||
export default function encode (input?: null | Uint8Array | Array<null | Uint8Array>): Uint8Array {
|
||||
const encoded = _encode(input);
|
||||
|
||||
// l.debug(() => ['encode', { input, encoded }]);
|
||||
|
||||
return encoded;
|
||||
}
|
||||
Reference in New Issue
Block a user