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:
Jaco Greeff
2018-11-22 14:29:34 +01:00
committed by GitHub
parent 5c5b7077cc
commit f82092e603
99 changed files with 2576 additions and 1096 deletions
+100
View File
@@ -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;
}