Combine util, types & trie into common (#150)
* Pull in trie repo * Bring in types repo
This commit is contained in:
23
README.md
23
README.md
@@ -13,13 +13,32 @@
|
||||
|
||||
Various useful utility functions that are used across all projects in the [@polkadot](https://polkadot.js.org) namespace. It provides utility functions with additional safety checks, allowing not only for consistent coding, but also reducing the general boilerplate.
|
||||
|
||||
It is split up into a number of internal packages -
|
||||
It is split up into a number of internal packages, namely utilities -
|
||||
|
||||
- [util](packages/util/) General utilities
|
||||
- [util-crypto](packages/util-crypto/) Crypto and hashing utilities
|
||||
- [util-keyring](packages/util-keyring/) Keyring management
|
||||
- [util-rlp](packages/util-rlp/) RLP encoding & decoding
|
||||
- [util-triehash](packages/util-triehash/) Calculation of trie hashes
|
||||
|
||||
Various useful trie interfaces and utilities -
|
||||
|
||||
- [trie-db](packages/trie-db/) Merkle Patricia Tree implementation adapcted for Polkadot
|
||||
- [trie-hash](packages/trie-hash/) Calculate hashes (either ordered or unordered) from a set of inputs
|
||||
|
||||
Type definitions for interfaces as exposed by Polkadot & Substrate clients -
|
||||
|
||||
- [@polkadot/extrinsics](packages/type-extrinsics/) Base extrinsic definitions
|
||||
- [@polkadot/jsonrpc](packages/type-jsonrpc/) Definitions for JSONRPC endpoints
|
||||
- [@polkadot/params](packages/type-params/) Input/output parameter formatting
|
||||
- [@polkadot/primitives](packages/type-primitives/) Primitive type definitions
|
||||
- [@polkadot/storage](packages/type-storage/) Definitions for storage entries
|
||||
|
||||
Codecs for types (possibly to be combined with types) -
|
||||
|
||||
- [@polkadot/extrinsics-codec](packages/code-extrinsics/) Encoders for extrinsics
|
||||
- [@polkadot/primitives-codec](packages/code-primitives/) Primitive encoding/decoding
|
||||
- [@polkadot/primitives-builder](packages/code-primitives-builder/) Primitive creator
|
||||
- [@polkadot/primitives-json](packages/code-primitives-json/) Primitive json encoding/decoding
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
@@ -2,7 +2,18 @@ const config = require('@polkadot/dev/config/jest');
|
||||
|
||||
module.exports = Object.assign({}, config, {
|
||||
moduleNameMapper: {
|
||||
'@polkadot/util-(crypto|keyring|rlp|triehash)(.*)$': '<rootDir>/packages/util-$1/src/$2',
|
||||
'@polkadot/extrinsics-codec(.*)$': '<rootDir>/packages/code-extrinsics/src/$1',
|
||||
'@polkadot/primitives-codec(.*)$': '<rootDir>/packages/code-primitives/src/$1',
|
||||
'@polkadot/primitives-(builder|json)(.*)$': '<rootDir>/packages/code-primitives-$1/src/$2',
|
||||
|
||||
'@polkadot/extrinsics(.*)$': '<rootDir>/packages/type-extrinsics/src/$1',
|
||||
'@polkadot/jsonrpc(.*)$': '<rootDir>/packages/type-jsonrpc/src/$1',
|
||||
'@polkadot/params(.*)$': '<rootDir>/packages/type-params/src/$1',
|
||||
'@polkadot/primitives(.*)$': '<rootDir>/packages/type-primitives/src/$1',
|
||||
'@polkadot/storage(.*)$': '<rootDir>/packages/type-storage/src/$1',
|
||||
|
||||
'@polkadot/trie-(db|hash)(.*)$': '<rootDir>/packages/trie-$1/src/$2',
|
||||
'@polkadot/util-(crypto|keyring|rlp)(.*)$': '<rootDir>/packages/util-$1/src/$2',
|
||||
'@polkadot/util(.*)$': '<rootDir>/packages/util/src/$1'
|
||||
}
|
||||
});
|
||||
|
||||
@@ -10,5 +10,5 @@
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "0.24.9"
|
||||
"version": "0.25.0"
|
||||
}
|
||||
|
||||
15
packages/code-extrinsics/LICENSE
Normal file
15
packages/code-extrinsics/LICENSE
Normal file
@@ -0,0 +1,15 @@
|
||||
ISC License (ISC)
|
||||
|
||||
Copyright 2017-2018 @polkadot/extrinsics-codec authors & contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
1
packages/code-extrinsics/README.md
Normal file
1
packages/code-extrinsics/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# @polkadot/extrinsics-codec
|
||||
25
packages/code-extrinsics/package.json
Normal file
25
packages/code-extrinsics/package.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "@polkadot/extrinsics-codec",
|
||||
"version": "0.25.0",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/polkadot-js/apps.git",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"maintainers": [
|
||||
"Jaco Greeff <jacogr@gmail.com>"
|
||||
],
|
||||
"contributors": [],
|
||||
"license": "ISC",
|
||||
"scripts": {
|
||||
"build": "polkadot-dev-build-babel",
|
||||
"check": "stylelint 'src/**/*.css' && eslint src && flow check",
|
||||
"test": "jest --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.0.0-beta.51",
|
||||
"@polkadot/extrinsics": "^0.25.0",
|
||||
"@polkadot/params": "^0.25.0",
|
||||
"@polkadot/util": "^0.25.0",
|
||||
"@polkadot/util-keyring": "^0.25.0",
|
||||
"bn.js": "^4.11.8"
|
||||
}
|
||||
}
|
||||
13
packages/code-extrinsics/src/decode/length.ts
Normal file
13
packages/code-extrinsics/src/decode/length.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2017-2018 @polkadot/extrinsics-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { UncheckedRaw } from '@polkadot/primitives/extrinsic';
|
||||
|
||||
import u8aToBn from '@polkadot/util/u8a/toBn';
|
||||
|
||||
export default function decodeLength (unchecked: Uint8Array): UncheckedRaw {
|
||||
const length = u8aToBn(unchecked.subarray(0, 4), true).toNumber();
|
||||
|
||||
return unchecked.slice(4, length + 4);
|
||||
}
|
||||
52
packages/code-extrinsics/src/encode/call.spec.js
Normal file
52
packages/code-extrinsics/src/encode/call.spec.js
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2017-2018 @polkadot/extrinsics-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import testingPairs from '@polkadot/util-keyring/testingPairs';
|
||||
|
||||
import call from './call';
|
||||
|
||||
const keyring = testingPairs();
|
||||
|
||||
describe('call', () => {
|
||||
it('encodes the call correctly (poc-1)', () => {
|
||||
expect(
|
||||
call(
|
||||
keyring.one.publicKey(),
|
||||
1234,
|
||||
new Uint8Array([0xab, 0xcd]),
|
||||
'poc-1'
|
||||
)
|
||||
).toEqual(
|
||||
new Uint8Array([
|
||||
// key
|
||||
47, 140, 97, 41, 216, 22, 207, 81, 195, 116, 188, 127, 8, 195, 230, 62, 209, 86, 207, 120, 174, 251, 74, 101, 80, 217, 123, 135, 153, 121, 119, 238,
|
||||
// nonce (u64)
|
||||
210, 4, 0, 0, 0, 0, 0, 0,
|
||||
// data
|
||||
171, 205
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
it('encodes the call correctly (latest)', () => {
|
||||
expect(
|
||||
call(
|
||||
keyring.one.publicKey(),
|
||||
1234,
|
||||
new Uint8Array([0xab, 0xcd]),
|
||||
'latest'
|
||||
)
|
||||
).toEqual(
|
||||
new Uint8Array([
|
||||
// key
|
||||
47, 140, 97, 41, 216, 22, 207, 81, 195, 116, 188, 127, 8, 195, 230, 62, 209, 86, 207, 120, 174, 251, 74, 101, 80, 217, 123, 135, 153, 121, 119, 238,
|
||||
// nonce (u32)
|
||||
210, 4, 0, 0,
|
||||
// data
|
||||
171, 205
|
||||
])
|
||||
);
|
||||
});
|
||||
});
|
||||
19
packages/code-extrinsics/src/encode/call.ts
Normal file
19
packages/code-extrinsics/src/encode/call.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright 2017-2018 @polkadot/extrinsics-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { EncodingVersions } from '@polkadot/params/types';
|
||||
import { ExtrinsicWithAccount, ExtrinsicWithIndex } from '../types';
|
||||
|
||||
import sizes from '@polkadot/params/sizes';
|
||||
import bnToU8a from '@polkadot/util/bn/toU8a';
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
|
||||
export default function encodeCall (publicKey: Uint8Array, nonce: number | BN, data: ExtrinsicWithIndex, version: EncodingVersions): ExtrinsicWithAccount {
|
||||
return u8aConcat(
|
||||
publicKey,
|
||||
bnToU8a(nonce, sizes.Index.get(version), true),
|
||||
data
|
||||
);
|
||||
}
|
||||
27
packages/code-extrinsics/src/encode/extrinsic.spec.js
Normal file
27
packages/code-extrinsics/src/encode/extrinsic.spec.js
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright 2017-2018 @polkadot/extrinsics-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import extrinsics from '@polkadot/extrinsics';
|
||||
|
||||
import extrinsic from './extrinsic';
|
||||
|
||||
describe('extrinsic', () => {
|
||||
it('encodes extrinsic correctly', () => {
|
||||
expect(
|
||||
extrinsic(
|
||||
extrinsics.timestamp.public.set,
|
||||
[10101],
|
||||
'latest'
|
||||
)
|
||||
).toEqual(
|
||||
new Uint8Array([
|
||||
// index
|
||||
3, 0,
|
||||
// values
|
||||
117, 39, 0, 0, 0, 0, 0, 0
|
||||
])
|
||||
);
|
||||
});
|
||||
});
|
||||
17
packages/code-extrinsics/src/encode/extrinsic.ts
Normal file
17
packages/code-extrinsics/src/encode/extrinsic.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2017-2018 @polkadot/extrinsics-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Extrinsics } from '@polkadot/extrinsics/types';
|
||||
import { EncodingVersions, SectionItem } from '@polkadot/params/types';
|
||||
import { ExtrinsicWithIndex } from '../types';
|
||||
|
||||
import encodeParams from '@polkadot/params/encode';
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
|
||||
export default function encodeExtrinsic (extrinsic: SectionItem<Extrinsics>, values: Array<any>, version: EncodingVersions): ExtrinsicWithIndex {
|
||||
return u8aConcat(
|
||||
extrinsic.index,
|
||||
encodeParams(extrinsic.params, values, version)
|
||||
);
|
||||
}
|
||||
34
packages/code-extrinsics/src/encode/index.spec.js
Normal file
34
packages/code-extrinsics/src/encode/index.spec.js
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright 2017-2018 @polkadot/extrinsics-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import extrinsics from '@polkadot/extrinsics';
|
||||
import testingPairs from '@polkadot/util-keyring/testingPairs';
|
||||
|
||||
import encode from './index';
|
||||
|
||||
const keyring = testingPairs();
|
||||
|
||||
describe('encode', () => {
|
||||
it('encodes extrinsic correctly', () => {
|
||||
expect(
|
||||
encode(keyring.nobody.publicKey(), 1234)(
|
||||
extrinsics.timestamp.public.set,
|
||||
[10101],
|
||||
'latest'
|
||||
)
|
||||
).toEqual(
|
||||
new Uint8Array([
|
||||
// publicKey
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// account nonce
|
||||
210, 4, 0, 0,
|
||||
// extrinsic index
|
||||
3, 0,
|
||||
// values
|
||||
117, 39, 0, 0, 0, 0, 0, 0
|
||||
])
|
||||
);
|
||||
});
|
||||
});
|
||||
23
packages/code-extrinsics/src/encode/index.ts
Normal file
23
packages/code-extrinsics/src/encode/index.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright 2017-2018 @polkadot/extrinsics-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Extrinsics } from '@polkadot/extrinsics/types';
|
||||
import { EncodingVersions, SectionItem } from '@polkadot/params/types';
|
||||
import { ExtrinsicWithAccount } from '../types';
|
||||
|
||||
import encodeCall from './call';
|
||||
import encodeExtrinsic from './extrinsic';
|
||||
|
||||
type Encoder = (extrinsic: SectionItem<Extrinsics>, values: Array<any>, version: EncodingVersions) => ExtrinsicWithAccount;
|
||||
|
||||
export default function encode (publicKey: Uint8Array, index: number | BN): Encoder {
|
||||
return (extrinsic: SectionItem<Extrinsics>, values: Array<any>, version: EncodingVersions): ExtrinsicWithAccount =>
|
||||
encodeCall(
|
||||
publicKey,
|
||||
index,
|
||||
encodeExtrinsic(extrinsic, values, version),
|
||||
version
|
||||
);
|
||||
}
|
||||
15
packages/code-extrinsics/src/encode/length.ts
Normal file
15
packages/code-extrinsics/src/encode/length.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2017-2018 @polkadot/extrinsics-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { UncheckedRaw } from '@polkadot/primitives/extrinsic';
|
||||
|
||||
import bnToU8a from '@polkadot/util/bn/toU8a';
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
|
||||
export default function encodeLength (unchecked: UncheckedRaw): Uint8Array {
|
||||
return u8aConcat(
|
||||
bnToU8a(unchecked.length, 32, true),
|
||||
unchecked
|
||||
);
|
||||
}
|
||||
25
packages/code-extrinsics/src/encode/prefixes.ts
Normal file
25
packages/code-extrinsics/src/encode/prefixes.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2017-2018 @polkadot/extrinsics-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
// https://github.com/paritytech/polkadot/pull/195
|
||||
// 0xff, 32-byte account id
|
||||
// 0xfe, 8-byte account index
|
||||
// 0xfd, 4-byte account index
|
||||
// 0xfc, 2-byte account index
|
||||
// [0xf0...0xfb] (invalid, reserved for future use)
|
||||
// [0x00...0xef] 1-byte account index (less than 0xf0)
|
||||
|
||||
const bytes8 = new Uint8Array([0xfe]);
|
||||
const bytes4 = new Uint8Array([0xfd]);
|
||||
const bytes2 = new Uint8Array([0xfc]);
|
||||
const none = new Uint8Array([]);
|
||||
const publicKey = new Uint8Array([0xff]);
|
||||
|
||||
export default {
|
||||
bytes8,
|
||||
bytes4,
|
||||
bytes2,
|
||||
none,
|
||||
publicKey
|
||||
};
|
||||
115
packages/code-extrinsics/src/encode/unchecked.spec.js
Normal file
115
packages/code-extrinsics/src/encode/unchecked.spec.js
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright 2017-2018 @polkadot/extrinsics-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import extrinsics from '@polkadot/extrinsics';
|
||||
import hexToU8a from '@polkadot/util/hex/toU8a';
|
||||
import testingPairs from '@polkadot/util-keyring/testingPairs';
|
||||
|
||||
import encode from './unchecked';
|
||||
|
||||
const keyring = testingPairs();
|
||||
|
||||
describe('unchecked', () => {
|
||||
it('encodes extrinsic correctly (nobody)', () => {
|
||||
expect(
|
||||
encode(keyring.nobody, 1234)(
|
||||
extrinsics.timestamp.public.set,
|
||||
[10101]
|
||||
)
|
||||
).toEqual(
|
||||
new Uint8Array([
|
||||
255,
|
||||
// publicKey
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// account nonce
|
||||
210, 4, 0, 0,
|
||||
// extrinsic index
|
||||
3, 0,
|
||||
// values
|
||||
117, 39, 0, 0, 0, 0, 0, 0,
|
||||
// signature
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
it('encodes extrinsic correctly (one)', () => {
|
||||
expect(
|
||||
encode(keyring.one, 258, 'poc-1')(
|
||||
extrinsics.staking.public.transfer,
|
||||
[keyring.two.publicKey(), 69]
|
||||
)
|
||||
).toEqual(
|
||||
new Uint8Array([
|
||||
// publicKey
|
||||
47, 140, 97, 41, 216, 22, 207, 81, 195, 116, 188, 127, 8, 195, 230, 62, 209, 86, 207, 120, 174, 251, 74, 101, 80, 217, 123, 135, 153, 121, 119, 238,
|
||||
// account nonce
|
||||
2, 1, 0, 0, 0, 0, 0, 0,
|
||||
// extrinsic index
|
||||
2, 0,
|
||||
// values
|
||||
// (recipient)
|
||||
215, 90, 152, 1, 130, 177, 10, 183, 213, 75, 254, 211, 201, 100, 7, 58, 14, 225, 114, 243, 218, 166, 35, 37, 175, 2, 26, 104, 247, 7, 81, 26,
|
||||
// (amount)
|
||||
69, 0, 0, 0, 0, 0, 0, 0,
|
||||
// signature
|
||||
144, 233, 93, 195, 106, 86, 2, 230, 182, 5, 62, 128, 120, 148, 21, 128, 86, 5, 74, 15, 128, 100, 255, 179, 172, 13, 102, 206, 117, 208, 175, 107, 107, 77, 209, 126, 129, 51, 1, 198, 184, 202, 100, 240, 0, 118, 150, 188, 67, 10, 154, 84, 224, 103, 17, 151, 163, 45, 78, 249, 219, 169, 96, 2
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
it('encodes extrinsic correctly (one + latest)', () => {
|
||||
expect(
|
||||
encode(keyring.one, 258)(
|
||||
extrinsics.staking.public.transfer,
|
||||
[keyring.two.publicKey(), 69]
|
||||
)
|
||||
).toEqual(
|
||||
new Uint8Array([
|
||||
255,
|
||||
// publicKey
|
||||
47, 140, 97, 41, 216, 22, 207, 81, 195, 116, 188, 127, 8, 195, 230, 62, 209, 86, 207, 120, 174, 251, 74, 101, 80, 217, 123, 135, 153, 121, 119, 238,
|
||||
// account nonce
|
||||
2, 1, 0, 0,
|
||||
// extrinsic index
|
||||
2, 0,
|
||||
// values
|
||||
// (recipient)
|
||||
255,
|
||||
215, 90, 152, 1, 130, 177, 10, 183, 213, 75, 254, 211, 201, 100, 7, 58, 14, 225, 114, 243, 218, 166, 35, 37, 175, 2, 26, 104, 247, 7, 81, 26,
|
||||
// (amount)
|
||||
69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// signature
|
||||
56, 1, 89, 195, 60, 171, 128, 242, 136, 64, 45, 43, 252, 199, 13, 115, 2, 76, 9, 19, 16, 80, 38, 164, 58, 229, 107, 225, 141, 107, 115, 176, 241, 242, 153, 177, 48, 92, 6, 61, 104, 112, 45, 223, 86, 198, 203, 78, 240, 223, 59, 190, 156, 116, 135, 188, 244, 219, 182, 58, 39, 140, 159, 11
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
it('encodes timetamp.set extrinsic correctly (actual values)', () => {
|
||||
expect(
|
||||
encode(keyring.nobody, 0)(
|
||||
extrinsics.timestamp.public.set,
|
||||
[0x5b13c37b]
|
||||
)
|
||||
).toEqual(
|
||||
hexToU8a(
|
||||
'0xff00000000000000000000000000000000000000000000000000000000000000000000000003007bc3135b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('encoded parachains.setHeads correctly (actual values)', () => {
|
||||
expect(
|
||||
encode(keyring.nobody, 0)(
|
||||
extrinsics.parachains.public.setHeads,
|
||||
[[]]
|
||||
)
|
||||
).toEqual(
|
||||
hexToU8a(
|
||||
'0xff00000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
33
packages/code-extrinsics/src/encode/unchecked.ts
Normal file
33
packages/code-extrinsics/src/encode/unchecked.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2017-2018 @polkadot/extrinsics-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Extrinsics } from '@polkadot/extrinsics/types';
|
||||
import { EncodingVersions, SectionItem } from '@polkadot/params/types';
|
||||
import { UncheckedRaw } from '@polkadot/primitives/extrinsic';
|
||||
import { KeyringPair } from '@polkadot/util-keyring/types';
|
||||
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
|
||||
import encode from './index';
|
||||
import prefixes from './prefixes';
|
||||
|
||||
type Encoder = (extrinsic: SectionItem<Extrinsics>, values: Array<any>) => UncheckedRaw;
|
||||
|
||||
export default function unchecked (pair: KeyringPair, index: number | BN, version: EncodingVersions = 'latest'): Encoder {
|
||||
const encoder = encode(pair.publicKey(), index);
|
||||
|
||||
return (extrinsic: SectionItem<Extrinsics>, values: Array<any>): UncheckedRaw => {
|
||||
const message = encoder(extrinsic, values, version);
|
||||
const signature = pair.sign(message);
|
||||
|
||||
return u8aConcat(
|
||||
version === 'poc-1'
|
||||
? prefixes.none
|
||||
: prefixes.publicKey,
|
||||
message,
|
||||
signature
|
||||
);
|
||||
};
|
||||
}
|
||||
9
packages/code-extrinsics/src/types.d.ts
vendored
Normal file
9
packages/code-extrinsics/src/types.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2017-2018 @polkadot/extrinsics-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
export type ExtrinsicWithAccount = Uint8Array;
|
||||
|
||||
export type ExtrinsicWithIndex = Uint8Array;
|
||||
|
||||
export type ExtrinsicUnchecked = Uint8Array;
|
||||
15
packages/code-primitives-builder/LICENSE
Normal file
15
packages/code-primitives-builder/LICENSE
Normal file
@@ -0,0 +1,15 @@
|
||||
ISC License (ISC)
|
||||
|
||||
Copyright 2017-2018 @polkadot/primitives-builder authors & contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
13
packages/code-primitives-builder/README.md
Normal file
13
packages/code-primitives-builder/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
[](https://polkadot.js.org)
|
||||

|
||||
[](https://github.com/Flet/semistandard)
|
||||
[](https://www.npmjs.com/package/@polkadot/primitives-builder)
|
||||
[](https://travis-ci.org/polkadot-js/types)
|
||||
[](https://codeclimate.com/github/polkadot-js/types/maintainability)
|
||||
[](https://coveralls.io/github/polkadot-js/types?branch=master)
|
||||
[](https://david-dm.org/polkadot-js/types?path=packages/primitives-builder)
|
||||
[](https://david-dm.org/polkadot-js/types?path=packages/primitives-builder#info=devDependencies)
|
||||
|
||||
# @polkadot/primitives-builder
|
||||
|
||||
Creating of primitive types.
|
||||
47
packages/code-primitives-builder/package.json
Normal file
47
packages/code-primitives-builder/package.json
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "@polkadot/primitives-builder",
|
||||
"version": "0.25.0",
|
||||
"description": "Builder for primitives for Polkadot",
|
||||
"main": "index.js",
|
||||
"engines": {
|
||||
"node": ">=6.4"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/polkadot-js/types.git"
|
||||
},
|
||||
"keywords": [
|
||||
"Polkadot"
|
||||
],
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"maintainers": [
|
||||
"Jaco Greeff <jacogr@gmail.com>"
|
||||
],
|
||||
"contributors": [],
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/polkadot-js/types/issues"
|
||||
},
|
||||
"homepage": "https://github.com/polkadot-js/types/tree/master/packages/primitives-builder#readme",
|
||||
"scripts": {
|
||||
"build": "polkadot-dev-build-babel",
|
||||
"check": "eslint src && flow check",
|
||||
"test": "echo \"Tests only available from root wrapper\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.0.0-beta.51",
|
||||
"@polkadot/extrinsics-codec": "^0.25.0",
|
||||
"@polkadot/primitives": "^0.25.0",
|
||||
"@polkadot/primitives-codec": "^0.25.0",
|
||||
"@polkadot/trie-hash": "^0.25.0",
|
||||
"@polkadot/util": "^0.25.0",
|
||||
"@polkadot/util-crypto": "^0.25.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/util-keyring": "^0.25.0"
|
||||
}
|
||||
}
|
||||
82
packages/code-primitives-builder/src/block.spec.js
Normal file
82
packages/code-primitives-builder/src/block.spec.js
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-builder authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import BN from 'bn.js';
|
||||
import extrinsics from '@polkadot/extrinsics';
|
||||
import encodeUnchecked from '@polkadot/extrinsics-codec/encode/unchecked';
|
||||
import hexToU8a from '@polkadot/util/hex/toU8a';
|
||||
import testingPairs from '@polkadot/util-keyring/testingPairs';
|
||||
|
||||
import block from './block';
|
||||
|
||||
const keyring = testingPairs();
|
||||
|
||||
describe('block', () => {
|
||||
it('creates a complete block from incomplete details', () => {
|
||||
expect(
|
||||
block({})
|
||||
).toEqual({
|
||||
header: {
|
||||
digest: {
|
||||
logs: []
|
||||
},
|
||||
number: new BN(0),
|
||||
parentHash: new Uint8Array(32),
|
||||
stateRoot: new Uint8Array(32),
|
||||
extrinsicsRoot: new Uint8Array([
|
||||
86, 232, 31, 23, 27, 204, 85, 166, 255, 131, 69, 230, 146, 192, 248, 110, 91, 72, 224, 27, 153, 108, 173, 192, 1, 98, 47, 181, 227, 99, 180, 33
|
||||
])
|
||||
},
|
||||
extrinsics: []
|
||||
});
|
||||
});
|
||||
|
||||
it('creates a valid block, with defaults submitted', () => {
|
||||
const transactions = [
|
||||
encodeUnchecked(keyring.nobody, 0)(
|
||||
extrinsics.timestamp.public.set,
|
||||
[0x5b13c3a4]
|
||||
),
|
||||
encodeUnchecked(keyring.nobody, 0)(
|
||||
extrinsics.parachains.public.setHeads,
|
||||
[[]]
|
||||
)
|
||||
];
|
||||
|
||||
expect(
|
||||
block({
|
||||
header: {
|
||||
number: 1,
|
||||
parentHash: hexToU8a(
|
||||
'0x4545454545454545454545454545454545454545454545454545454545454545'
|
||||
),
|
||||
stateRoot: hexToU8a(
|
||||
'0x2481853da20b9f4322f34650fea5f240dcbfb266d02db94bfa0153c31f4a29db'
|
||||
)
|
||||
},
|
||||
extrinsics: transactions
|
||||
})
|
||||
).toEqual({
|
||||
header: {
|
||||
digest: {
|
||||
logs: []
|
||||
},
|
||||
number: new BN(1),
|
||||
parentHash: hexToU8a(
|
||||
'0x4545454545454545454545454545454545454545454545454545454545454545'
|
||||
),
|
||||
stateRoot: hexToU8a(
|
||||
'0x2481853da20b9f4322f34650fea5f240dcbfb266d02db94bfa0153c31f4a29db'
|
||||
),
|
||||
extrinsicsRoot: new Uint8Array([
|
||||
140, 102, 133, 98, 214, 123, 73, 173, 122, 252, 247, 48, 181, 86, 77, 188, 213, 161, 17, 19, 73, 96, 158, 181, 249, 69, 97, 15, 186, 12, 45, 157
|
||||
])
|
||||
// hexToU8a(
|
||||
// '0xab602f7974bbfb513f021f39777e2195094dc64a2c1b7c82a1781cb9fd4768a8'
|
||||
// )
|
||||
},
|
||||
extrinsics: transactions
|
||||
});
|
||||
});
|
||||
});
|
||||
15
packages/code-primitives-builder/src/block.ts
Normal file
15
packages/code-primitives-builder/src/block.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-builder authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Block } from '@polkadot/primitives/block';
|
||||
import { BlockIncomplete } from './types';
|
||||
|
||||
import headerBuilder from './header';
|
||||
|
||||
export default function block ({ header = {}, extrinsics = [] }: BlockIncomplete): Block {
|
||||
return {
|
||||
header: headerBuilder(header, extrinsics),
|
||||
extrinsics
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-builder authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import extrinsics from '@polkadot/extrinsics';
|
||||
import encodeUnchecked from '@polkadot/extrinsics-codec/encode/unchecked';
|
||||
import hexToU8a from '@polkadot/util/hex/toU8a';
|
||||
import testingPairs from '@polkadot/util-keyring/testingPairs';
|
||||
|
||||
import root from './rootRaw';
|
||||
|
||||
const keyring = testingPairs();
|
||||
|
||||
describe('root', () => {
|
||||
it('calculates the root correctly for no transactions', () => {
|
||||
expect(
|
||||
root()
|
||||
).toEqual(
|
||||
hexToU8a(
|
||||
'0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421'
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('calculates the root correctly (actual)', () => {
|
||||
expect(
|
||||
root([
|
||||
encodeUnchecked(keyring.nobody, 0)(
|
||||
extrinsics.timestamp.public.set,
|
||||
[0x5b13c3a4]
|
||||
),
|
||||
encodeUnchecked(keyring.nobody, 0)(
|
||||
extrinsics.parachains.public.setHeads,
|
||||
[[]]
|
||||
)
|
||||
])
|
||||
).toEqual(
|
||||
new Uint8Array([
|
||||
140, 102, 133, 98, 214, 123, 73, 173, 122, 252, 247, 48, 181, 86, 77, 188, 213, 161, 17, 19, 73, 96, 158, 181, 249, 69, 97, 15, 186, 12, 45, 157
|
||||
])
|
||||
// hexToU8a(
|
||||
// '0xab602f7974bbfb513f021f39777e2195094dc64a2c1b7c82a1781cb9fd4768a8'
|
||||
// )
|
||||
);
|
||||
});
|
||||
|
||||
// [
|
||||
// 168, 135, 224, 93, 140, 222, 226, 83, 13, 116, 138, 197, 164, 6, 48, 190, 101, 18, 221, 166, 40, 179, 158, 112, 133, 154, 215, 198, 177, 76, 212, 228,
|
||||
// 1, 0, 0, 0, 0, 0, 0, 0,
|
||||
// 159, 216, 180, 61, 159, 12, 131, 80, 22, 196, 220, 94, 6, 222, 68, 159, 97, 60, 16, 69, 163, 149, 125, 138, 175, 36, 30, 93, 235, 4, 1, 168,
|
||||
// 245, 208, 141, 24, 250, 136, 158, 84, 67, 170, 59, 146, 17, 149, 62, 67, 254, 66, 126, 53, 20, 146, 252, 243, 137, 89, 224, 145, 252, 79, 109, 15,
|
||||
// 0, 0, 0, 0,
|
||||
// 2, 0, 0, 0,
|
||||
// 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 188, 29, 21, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
|
||||
it('calculates the root correctly (actual encoded)', () => {
|
||||
expect(
|
||||
root([
|
||||
new Uint8Array([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
3, 0,
|
||||
188, 29, 21, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
]),
|
||||
new Uint8Array([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
])
|
||||
])
|
||||
).toEqual(
|
||||
new Uint8Array([
|
||||
245, 208, 141, 24, 250, 136, 158, 84, 67, 170, 59, 146, 17, 149, 62, 67, 254, 66, 126, 53, 20, 146, 252, 243, 137, 89, 224, 145, 252, 79, 109, 15
|
||||
])
|
||||
);
|
||||
});
|
||||
});
|
||||
14
packages/code-primitives-builder/src/extrinsic/rootRaw.ts
Normal file
14
packages/code-primitives-builder/src/extrinsic/rootRaw.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-builder authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { UncheckedRaw } from '@polkadot/primitives/extrinsic';
|
||||
|
||||
import uncheckedLength from '@polkadot/extrinsics-codec/encode/length';
|
||||
import trieRootOrdered from '@polkadot/trie-hash/rootOrdered';
|
||||
|
||||
export default function extrinsicsRootRaw (extrinsics: Array<UncheckedRaw> = []): Uint8Array {
|
||||
return trieRootOrdered(
|
||||
extrinsics.map(uncheckedLength)
|
||||
);
|
||||
}
|
||||
41
packages/code-primitives-builder/src/header.spec.js
Normal file
41
packages/code-primitives-builder/src/header.spec.js
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-builder authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import txRoot from './extrinsic/rootRaw';
|
||||
import extrinsics from '@polkadot/extrinsics';
|
||||
import encodeUnchecked from '@polkadot/extrinsics-codec/encode/unchecked';
|
||||
import testingPairs from '@polkadot/util-keyring/testingPairs';
|
||||
|
||||
import header from './header';
|
||||
|
||||
const keyring = testingPairs();
|
||||
|
||||
describe('header', () => {
|
||||
it('applies the all transactions (no timestamp)', () => {
|
||||
expect(
|
||||
header({}).extrinsicsRoot
|
||||
).toEqual(
|
||||
txRoot([])
|
||||
);
|
||||
});
|
||||
|
||||
it('applies the all transactions (extrinsicsRoot)', () => {
|
||||
const transactions = [
|
||||
encodeUnchecked(keyring.nobody, 0)(
|
||||
extrinsics.timestamp.public.set,
|
||||
[54321]
|
||||
),
|
||||
encodeUnchecked(keyring.one, 0)(
|
||||
extrinsics.timestamp.public.set,
|
||||
[12345]
|
||||
)
|
||||
];
|
||||
|
||||
expect(
|
||||
header({}, transactions).extrinsicsRoot
|
||||
).toEqual(
|
||||
txRoot(transactions)
|
||||
);
|
||||
});
|
||||
});
|
||||
25
packages/code-primitives-builder/src/header.ts
Normal file
25
packages/code-primitives-builder/src/header.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-builder authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Header } from '@polkadot/primitives/header';
|
||||
import { UncheckedRaw } from '@polkadot/primitives/extrinsic';
|
||||
import { HeaderIncomplete } from './types';
|
||||
|
||||
import bnToBn from '@polkadot/util/bn/toBn';
|
||||
|
||||
import extrinsicsRawRoot from './extrinsic/rootRaw';
|
||||
|
||||
export default function header ({ digest: { logs = [] } = {}, extrinsicsRoot, number, parentHash = new Uint8Array(32), stateRoot = new Uint8Array(32) }: HeaderIncomplete, extrinsics?: Array<UncheckedRaw>): Header {
|
||||
return {
|
||||
digest: {
|
||||
logs
|
||||
},
|
||||
extrinsicsRoot: extrinsics
|
||||
? extrinsicsRawRoot(extrinsics)
|
||||
: (extrinsicsRoot || extrinsicsRawRoot([])),
|
||||
number: bnToBn(number || 0),
|
||||
parentHash,
|
||||
stateRoot
|
||||
};
|
||||
}
|
||||
22
packages/code-primitives-builder/src/types.d.ts
vendored
Normal file
22
packages/code-primitives-builder/src/types.d.ts
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-builder authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { BlockNumber, Hash, HeaderHash } from '@polkadot/primitives/base';
|
||||
import { Digest$Log } from '@polkadot/primitives/digest';
|
||||
import { UncheckedRaw } from '@polkadot/primitives/extrinsic';
|
||||
|
||||
export type HeaderIncomplete = {
|
||||
digest?: {
|
||||
logs?: Array<Digest$Log>
|
||||
},
|
||||
extrinsicsRoot?: Hash,
|
||||
parentHash?: HeaderHash,
|
||||
number?: BlockNumber | number,
|
||||
stateRoot?: Hash
|
||||
};
|
||||
|
||||
export type BlockIncomplete = {
|
||||
header?: HeaderIncomplete,
|
||||
extrinsics?: Array<UncheckedRaw>
|
||||
};
|
||||
15
packages/code-primitives-json/LICENSE
Normal file
15
packages/code-primitives-json/LICENSE
Normal file
@@ -0,0 +1,15 @@
|
||||
ISC License (ISC)
|
||||
|
||||
Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
33
packages/code-primitives-json/README.md
Normal file
33
packages/code-primitives-json/README.md
Normal file
@@ -0,0 +1,33 @@
|
||||
[](https://polkadot.js.org)
|
||||

|
||||
[](https://github.com/Flet/semistandard)
|
||||
[](https://www.npmjs.com/package/@polkadot/primitives-json)
|
||||
[](https://travis-ci.org/polkadot-js/types)
|
||||
[](https://codeclimate.com/github/polkadot-js/types/maintainability)
|
||||
[](https://coveralls.io/github/polkadot-js/types?branch=master)
|
||||
[](https://david-dm.org/polkadot-js/types?path=packages/primitives-json)
|
||||
[](https://david-dm.org/polkadot-js/types?path=packages/primitives-json#info=devDependencies)
|
||||
|
||||
# @polkadot/primitives-json
|
||||
|
||||
Conversion of Polkadot types to and from a structure with Json-only primitives, ready for serialisation. As such, it does not stringify itself, rather converts from complex classes to the correct Json reprsentation.
|
||||
|
||||
## Usage
|
||||
|
||||
Installation -
|
||||
|
||||
```
|
||||
npm install --save @polkadot/primitives-json
|
||||
```
|
||||
|
||||
Usage -
|
||||
|
||||
```js
|
||||
const { parachainIdDecode, parachainIdEncode } from '@polkadot/primitives-json');
|
||||
|
||||
parachainIdDecode( // step 3 - BN `0x123456`
|
||||
parachainIdEncode( // step 1 - string `'0x123456'`
|
||||
new BN('0x123456') // step 0 - BN `0x123456`
|
||||
)
|
||||
);
|
||||
```
|
||||
41
packages/code-primitives-json/package.json
Normal file
41
packages/code-primitives-json/package.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "@polkadot/primitives-json",
|
||||
"version": "0.25.0",
|
||||
"description": "Conversion utilities for primitives for JSON representation",
|
||||
"main": "index.js",
|
||||
"engines": {
|
||||
"node": ">=6.4"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/polkadot-js/types.git"
|
||||
},
|
||||
"keywords": [
|
||||
"Polkadot"
|
||||
],
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"maintainers": [
|
||||
"Jaco Greeff <jacogr@gmail.com>"
|
||||
],
|
||||
"contributors": [],
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/polkadot-js/types/issues"
|
||||
},
|
||||
"homepage": "https://github.com/polkadot-js/types/tree/master/packages/primitives-json#readme",
|
||||
"scripts": {
|
||||
"build": "polkadot-dev-build-babel",
|
||||
"check": "eslint src && flow check",
|
||||
"test": "echo \"Tests only available from root wrapper\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.0.0-beta.51",
|
||||
"@polkadot/primitives": "^0.25.0",
|
||||
"@polkadot/primitives-builder": "^0.25.0",
|
||||
"@polkadot/util": "^0.25.0"
|
||||
}
|
||||
}
|
||||
12
packages/code-primitives-json/src/accountId/decode.ts
Normal file
12
packages/code-primitives-json/src/accountId/decode.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId } from '@polkadot/primitives/base';
|
||||
import { JsonAccountId } from '../types';
|
||||
|
||||
import hashDecode from '../hash/decode';
|
||||
|
||||
export default function accountIdDecode (value: JsonAccountId): AccountId {
|
||||
return hashDecode(value, 160);
|
||||
}
|
||||
12
packages/code-primitives-json/src/accountId/encode.ts
Normal file
12
packages/code-primitives-json/src/accountId/encode.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId } from '@polkadot/primitives/base';
|
||||
import { JsonAccountId } from '../types';
|
||||
|
||||
import hashEncode from '../hash/encode';
|
||||
|
||||
export default function accountIdEncode (value: AccountId): JsonAccountId {
|
||||
return hashEncode(value, 160);
|
||||
}
|
||||
11
packages/code-primitives-json/src/accountId/index.ts
Normal file
11
packages/code-primitives-json/src/accountId/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import accountIdDecode from './decode';
|
||||
import accountIdEncode from './encode';
|
||||
|
||||
export {
|
||||
accountIdDecode,
|
||||
accountIdEncode
|
||||
};
|
||||
25
packages/code-primitives-json/src/bn/decode.spec.js
Normal file
25
packages/code-primitives-json/src/bn/decode.spec.js
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { bnDecode } from './index';
|
||||
|
||||
describe('bnDecode', () => {
|
||||
it('converts hex to a BN value', () => {
|
||||
expect(
|
||||
bnDecode('0x1234').toNumber()
|
||||
).toEqual(0x1234);
|
||||
});
|
||||
|
||||
it('converts with the required bitLength', () => {
|
||||
expect(
|
||||
bnDecode('0x1234', 8).toNumber()
|
||||
).toEqual(0x34);
|
||||
});
|
||||
|
||||
it('converts a non-hex/numeric value', () => {
|
||||
expect(
|
||||
bnDecode(10).toNumber()
|
||||
).toEqual(10);
|
||||
});
|
||||
});
|
||||
20
packages/code-primitives-json/src/bn/decode.ts
Normal file
20
packages/code-primitives-json/src/bn/decode.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { JsonBnType } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import hexFixLength from '@polkadot/util/hex/fixLength';
|
||||
import isHex from '@polkadot/util/is/hex';
|
||||
import hexToBn from '@polkadot/util/hex/toBn';
|
||||
|
||||
export default function bnDecode (value: JsonBnType, bitLength: number = -1): BN {
|
||||
if (isHex(value)) {
|
||||
return hexToBn(
|
||||
hexFixLength(value, bitLength)
|
||||
);
|
||||
}
|
||||
|
||||
return new BN(value);
|
||||
}
|
||||
21
packages/code-primitives-json/src/bn/encode.spec.js
Normal file
21
packages/code-primitives-json/src/bn/encode.spec.js
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import { bnEncode } from './index';
|
||||
|
||||
describe('bnEncode', () => {
|
||||
it('converts to a hex string', () => {
|
||||
expect(
|
||||
bnEncode(new BN(0x1234))
|
||||
).toEqual('0x1234');
|
||||
});
|
||||
|
||||
it('converts to a hex with the provided bitLength', () => {
|
||||
expect(
|
||||
bnEncode(new BN(0x1234), 8)
|
||||
).toEqual('0x34');
|
||||
});
|
||||
});
|
||||
16
packages/code-primitives-json/src/bn/encode.ts
Normal file
16
packages/code-primitives-json/src/bn/encode.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { JsonBnType } from '../types';
|
||||
|
||||
import hexFixLength from '@polkadot/util/hex/fixLength';
|
||||
import bnToHex from '@polkadot/util/bn/toHex';
|
||||
|
||||
export default function bnEncode (value: BN | number, bitLength: number = -1): JsonBnType {
|
||||
return hexFixLength(
|
||||
bnToHex(value),
|
||||
bitLength
|
||||
);
|
||||
}
|
||||
11
packages/code-primitives-json/src/bn/index.ts
Normal file
11
packages/code-primitives-json/src/bn/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import bnDecode from './decode';
|
||||
import bnEncode from './encode';
|
||||
|
||||
export {
|
||||
bnDecode,
|
||||
bnEncode
|
||||
};
|
||||
13
packages/code-primitives-json/src/bytes/decode.spec.js
Normal file
13
packages/code-primitives-json/src/bytes/decode.spec.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { bytesDecode } from './index';
|
||||
|
||||
describe('bytesDecode', () => {
|
||||
it('creates the correct bytes U8a', () => {
|
||||
expect(
|
||||
bytesDecode('0x0012345600')
|
||||
).toEqual(new Uint8Array([0x00, 0x12, 0x34, 0x56, 0x00]));
|
||||
});
|
||||
});
|
||||
12
packages/code-primitives-json/src/bytes/decode.ts
Normal file
12
packages/code-primitives-json/src/bytes/decode.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Bytes } from '@polkadot/primitives/base';
|
||||
import { JsonBytes } from '../types';
|
||||
|
||||
import hexToU8a from '@polkadot/util/hex/toU8a';
|
||||
|
||||
export default function bytesDecode (value: JsonBytes): Bytes {
|
||||
return hexToU8a(value);
|
||||
}
|
||||
13
packages/code-primitives-json/src/bytes/encode.spec.js
Normal file
13
packages/code-primitives-json/src/bytes/encode.spec.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { bytesEncode } from './index';
|
||||
|
||||
describe('bytesEncode', () => {
|
||||
it('creates the correct bytes U8a', () => {
|
||||
expect(
|
||||
bytesEncode(new Uint8Array([0x00, 0x12, 0x34, 0x56, 0x00]))
|
||||
).toEqual('0x0012345600');
|
||||
});
|
||||
});
|
||||
12
packages/code-primitives-json/src/bytes/encode.ts
Normal file
12
packages/code-primitives-json/src/bytes/encode.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Bytes } from '@polkadot/primitives/base';
|
||||
import { JsonBytes } from '../types';
|
||||
|
||||
import u8aToHex from '@polkadot/util/u8a/toHex';
|
||||
|
||||
export default function bytesEncode (value: Bytes): JsonBytes {
|
||||
return u8aToHex(value);
|
||||
}
|
||||
11
packages/code-primitives-json/src/bytes/index.ts
Normal file
11
packages/code-primitives-json/src/bytes/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import bytesDecode from './decode';
|
||||
import bytesEncode from './encode';
|
||||
|
||||
export {
|
||||
bytesDecode,
|
||||
bytesEncode
|
||||
};
|
||||
19
packages/code-primitives-json/src/hash/decode.spec.js
Normal file
19
packages/code-primitives-json/src/hash/decode.spec.js
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { hashDecode } from './index';
|
||||
|
||||
describe('hashDecode', () => {
|
||||
it('returns the hash when no length specified', () => {
|
||||
expect(
|
||||
hashDecode('0x123456787890abcdef')
|
||||
).toEqual(new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x78, 0x90, 0xab, 0xcd, 0xef]));
|
||||
});
|
||||
|
||||
it('converts to the required length as specified', () => {
|
||||
expect(
|
||||
hashDecode('0x123456787890abcdef', 32)
|
||||
).toEqual(new Uint8Array([0x12, 0x34, 0x56, 0x78]));
|
||||
});
|
||||
});
|
||||
12
packages/code-primitives-json/src/hash/decode.ts
Normal file
12
packages/code-primitives-json/src/hash/decode.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Hash } from '@polkadot/primitives/base';
|
||||
import { JsonHash } from '../types';
|
||||
|
||||
import hexToU8a from '@polkadot/util/hex/toU8a';
|
||||
|
||||
export default function hashDecode (value: JsonHash, bitLength: number = -1): Hash {
|
||||
return hexToU8a(value, bitLength);
|
||||
}
|
||||
21
packages/code-primitives-json/src/hash/encode.spec.js
Normal file
21
packages/code-primitives-json/src/hash/encode.spec.js
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { hashEncode } from './index';
|
||||
|
||||
describe('hashEncode', () => {
|
||||
it('returns the hash when no length specified', () => {
|
||||
expect(
|
||||
hashEncode(
|
||||
new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x78, 0x90, 0xab, 0xcd, 0xef])
|
||||
)
|
||||
).toEqual('0x123456787890abcdef');
|
||||
});
|
||||
|
||||
it('converts to the required length as specified', () => {
|
||||
expect(
|
||||
hashEncode(new Uint8Array([0x34, 0x56, 0x78, 0x78, 0x90, 0xab, 0xcd, 0xef]), 64)
|
||||
).toEqual('0x3456787890abcdef');
|
||||
});
|
||||
});
|
||||
12
packages/code-primitives-json/src/hash/encode.ts
Normal file
12
packages/code-primitives-json/src/hash/encode.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Hash } from '@polkadot/primitives/base';
|
||||
import { JsonHash } from '../types';
|
||||
|
||||
import u8aToHex from '@polkadot/util/u8a/toHex';
|
||||
|
||||
export default function hashEncode (value: Hash, bitLength: number = -1): JsonHash {
|
||||
return u8aToHex(value);
|
||||
}
|
||||
11
packages/code-primitives-json/src/hash/index.ts
Normal file
11
packages/code-primitives-json/src/hash/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import hashDecode from './decode';
|
||||
import hashEncode from './encode';
|
||||
|
||||
export {
|
||||
hashDecode,
|
||||
hashEncode
|
||||
};
|
||||
38
packages/code-primitives-json/src/header/decode.spec.js
Normal file
38
packages/code-primitives-json/src/header/decode.spec.js
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import { headerDecode } from './index';
|
||||
|
||||
describe('headerDecode', () => {
|
||||
it('creates the correct structure', () => {
|
||||
expect(
|
||||
JSON.stringify(
|
||||
headerDecode({
|
||||
digest: {
|
||||
logs: ['0x5678', '0x789a']
|
||||
},
|
||||
extrinsicsRoot: '0xabcd',
|
||||
number: '0x1234',
|
||||
parentHash: '0x1234',
|
||||
stateRoot: '0x5678'
|
||||
})
|
||||
)
|
||||
).toEqual(
|
||||
JSON.stringify({
|
||||
digest: {
|
||||
logs: [
|
||||
new Uint8Array([0x56, 0x78]),
|
||||
new Uint8Array([0x78, 0x9a])
|
||||
]
|
||||
},
|
||||
extrinsicsRoot: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xab, 0xcd]),
|
||||
number: new BN(0x1234),
|
||||
parentHash: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x12, 0x34]),
|
||||
stateRoot: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x56, 0x78])
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
24
packages/code-primitives-json/src/header/decode.ts
Normal file
24
packages/code-primitives-json/src/header/decode.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Header } from '@polkadot/primitives/header';
|
||||
import { JsonHeader } from '../types';
|
||||
|
||||
import headerBuilder from '@polkadot/primitives-builder/header';
|
||||
|
||||
import hashDecode from '../hash/decode';
|
||||
import bnDecode from '../bn/decode';
|
||||
import bytesDecode from '../bytes/decode';
|
||||
|
||||
export default function headerDecode ({ digest, extrinsicsRoot, number, parentHash, stateRoot }: JsonHeader): Header {
|
||||
return headerBuilder({
|
||||
digest: {
|
||||
logs: digest.logs.map(bytesDecode)
|
||||
},
|
||||
extrinsicsRoot: hashDecode(extrinsicsRoot, 256),
|
||||
number: bnDecode(number, 64),
|
||||
parentHash: hashDecode(parentHash, 256),
|
||||
stateRoot: hashDecode(stateRoot, 256)
|
||||
});
|
||||
}
|
||||
38
packages/code-primitives-json/src/header/encode.spec.js
Normal file
38
packages/code-primitives-json/src/header/encode.spec.js
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import { headerEncode } from './index';
|
||||
|
||||
describe('headerEncode', () => {
|
||||
it('creates the correct structure', () => {
|
||||
expect(
|
||||
JSON.stringify(
|
||||
headerEncode({
|
||||
digest: {
|
||||
logs: [
|
||||
new Uint8Array([0x56, 0x78]),
|
||||
new Uint8Array([0x78, 0x9a])
|
||||
]
|
||||
},
|
||||
extrinsicsRoot: new Uint8Array([0xab, 0xcd]),
|
||||
number: new BN(0x1234),
|
||||
parentHash: new Uint8Array([0x12, 0x34]),
|
||||
stateRoot: new Uint8Array([0x56, 0x78])
|
||||
})
|
||||
)
|
||||
).toEqual(
|
||||
JSON.stringify({
|
||||
digest: {
|
||||
logs: ['0x5678', '0x789a']
|
||||
},
|
||||
extrinsicsRoot: '0xabcd',
|
||||
number: '0x1234',
|
||||
parentHash: '0x1234',
|
||||
stateRoot: '0x5678'
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
22
packages/code-primitives-json/src/header/encode.ts
Normal file
22
packages/code-primitives-json/src/header/encode.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Header } from '@polkadot/primitives/header';
|
||||
import { JsonHeader } from '../types';
|
||||
|
||||
import bnEncode from '../bn/encode';
|
||||
import bytesEncode from '../bytes/encode';
|
||||
import hashEncode from '../hash/encode';
|
||||
|
||||
export default function headerEncode ({ parentHash, number, stateRoot, extrinsicsRoot, digest }: Header): JsonHeader {
|
||||
return {
|
||||
digest: {
|
||||
logs: digest.logs.map(bytesEncode)
|
||||
},
|
||||
extrinsicsRoot: hashEncode(extrinsicsRoot, 256),
|
||||
number: bnEncode(number, 64),
|
||||
parentHash: hashEncode(parentHash, 256),
|
||||
stateRoot: hashEncode(stateRoot, 256)
|
||||
};
|
||||
}
|
||||
11
packages/code-primitives-json/src/header/index.ts
Normal file
11
packages/code-primitives-json/src/header/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import headerDecode from './decode';
|
||||
import headerEncode from './encode';
|
||||
|
||||
export {
|
||||
headerDecode,
|
||||
headerEncode
|
||||
};
|
||||
12
packages/code-primitives-json/src/index.ts
Normal file
12
packages/code-primitives-json/src/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
export * from './accountId';
|
||||
export * from './header';
|
||||
export * from './bn';
|
||||
export * from './bytes';
|
||||
export * from './hash';
|
||||
export * from './objectId';
|
||||
export * from './parachainId';
|
||||
export * from './signature';
|
||||
12
packages/code-primitives-json/src/objectId/decode.ts
Normal file
12
packages/code-primitives-json/src/objectId/decode.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { ObjectId } from '@polkadot/primitives/base';
|
||||
import { JsonObjectId } from '../types';
|
||||
|
||||
import bnDecode from '../bn/decode';
|
||||
|
||||
export default function objectIdDecode (value: JsonObjectId): ObjectId {
|
||||
return bnDecode(value, 64);
|
||||
}
|
||||
12
packages/code-primitives-json/src/objectId/encode.ts
Normal file
12
packages/code-primitives-json/src/objectId/encode.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { ObjectId } from '@polkadot/primitives/base';
|
||||
import { JsonObjectId } from '../types';
|
||||
|
||||
import bnEncode from '../bn/encode';
|
||||
|
||||
export default function objectIdEncode (value: ObjectId): JsonObjectId {
|
||||
return bnEncode(value, 64);
|
||||
}
|
||||
11
packages/code-primitives-json/src/objectId/index.ts
Normal file
11
packages/code-primitives-json/src/objectId/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import objectIdDecode from './decode';
|
||||
import objectIdEncode from './encode';
|
||||
|
||||
export {
|
||||
objectIdDecode,
|
||||
objectIdEncode
|
||||
};
|
||||
12
packages/code-primitives-json/src/parachainId/decode.ts
Normal file
12
packages/code-primitives-json/src/parachainId/decode.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { ParaChainId } from '@polkadot/primitives/base';
|
||||
import { JsonParaChainId } from '../types';
|
||||
|
||||
import bnDecode from '../bn/decode';
|
||||
|
||||
export default function parachainIdDecode (value: JsonParaChainId): ParaChainId {
|
||||
return bnDecode(value, 64);
|
||||
}
|
||||
12
packages/code-primitives-json/src/parachainId/encode.ts
Normal file
12
packages/code-primitives-json/src/parachainId/encode.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { ParaChainId } from '@polkadot/primitives/base';
|
||||
import { JsonParaChainId } from '../types';
|
||||
|
||||
import bnEncode from '../bn/encode';
|
||||
|
||||
export default function parachainIdEncode (value: ParaChainId): JsonParaChainId {
|
||||
return bnEncode(value, 64);
|
||||
}
|
||||
11
packages/code-primitives-json/src/parachainId/index.ts
Normal file
11
packages/code-primitives-json/src/parachainId/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import parachainIdDecode from './decode';
|
||||
import parachainIdEncode from './encode';
|
||||
|
||||
export {
|
||||
parachainIdDecode,
|
||||
parachainIdEncode
|
||||
};
|
||||
12
packages/code-primitives-json/src/signature/decode.ts
Normal file
12
packages/code-primitives-json/src/signature/decode.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Signature } from '@polkadot/primitives/base';
|
||||
import { JsonSignature } from '../types';
|
||||
|
||||
import hashDecode from '../hash/decode';
|
||||
|
||||
export default function signatureDecode (value: JsonSignature): Signature {
|
||||
return hashDecode(value);
|
||||
}
|
||||
12
packages/code-primitives-json/src/signature/encode.ts
Normal file
12
packages/code-primitives-json/src/signature/encode.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Signature } from '@polkadot/primitives/base';
|
||||
import { JsonSignature } from '../types';
|
||||
|
||||
import hashEncode from '../hash/encode';
|
||||
|
||||
export default function signatureEncode (value: Signature): JsonSignature {
|
||||
return hashEncode(value);
|
||||
}
|
||||
11
packages/code-primitives-json/src/signature/index.ts
Normal file
11
packages/code-primitives-json/src/signature/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import signatureDecode from './decode';
|
||||
import signatureEncode from './encode';
|
||||
|
||||
export {
|
||||
signatureDecode,
|
||||
signatureEncode
|
||||
};
|
||||
51
packages/code-primitives-json/src/types.d.ts
vendored
Normal file
51
packages/code-primitives-json/src/types.d.ts
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-json authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
export type JsonBnType = string;
|
||||
export type JsonHash = string;
|
||||
|
||||
export type JsonBytes = string;
|
||||
export type JsonH160 = JsonHash;
|
||||
export type JsonH256 = JsonHash;
|
||||
export type JsonH512 = JsonHash;
|
||||
export type JsonHeaderHash = JsonH256;
|
||||
export type JsonU64 = JsonBnType;
|
||||
export type JsonU256 = JsonBnType;
|
||||
|
||||
export type JsonAccountId = JsonHash;
|
||||
export type JsonAuthorityId = JsonHash;
|
||||
export type JsonBlockNumber = JsonU64;
|
||||
export type JsonObjectId = JsonU64;
|
||||
export type JsonParaChainId = JsonU64;
|
||||
export type JsonSignature = JsonHash;
|
||||
|
||||
export type JsonTransaction = {
|
||||
from: JsonAuthorityId,
|
||||
to: JsonAuthorityId,
|
||||
amount: JsonBnType,
|
||||
nonce: JsonBnType
|
||||
}
|
||||
|
||||
export type JsonUnchecked = {
|
||||
tx: JsonTransaction,
|
||||
signature: JsonH512
|
||||
}
|
||||
|
||||
export type JsonDigest = {
|
||||
logs: Array<JsonBytes>
|
||||
};
|
||||
|
||||
export type JsonHeader = {
|
||||
parentHash: JsonHeaderHash,
|
||||
number: JsonBlockNumber,
|
||||
stateRoot: JsonHash,
|
||||
extrinsicsRoot: JsonHash,
|
||||
digest: JsonDigest
|
||||
};
|
||||
|
||||
export type JsonBlock = {
|
||||
header: JsonHeader,
|
||||
timestamp: JsonU64,
|
||||
transactions: Array<JsonUnchecked>
|
||||
};
|
||||
15
packages/code-primitives/LICENSE
Normal file
15
packages/code-primitives/LICENSE
Normal file
@@ -0,0 +1,15 @@
|
||||
ISC License (ISC)
|
||||
|
||||
Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
13
packages/code-primitives/README.md
Normal file
13
packages/code-primitives/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
[](https://polkadot.js.org)
|
||||

|
||||
[](https://github.com/Flet/semistandard)
|
||||
[](https://www.npmjs.com/package/@polkadot/primitives-codec)
|
||||
[](https://travis-ci.org/polkadot-js/types)
|
||||
[](https://codeclimate.com/github/polkadot-js/types/maintainability)
|
||||
[](https://coveralls.io/github/polkadot-js/types?branch=master)
|
||||
[](https://david-dm.org/polkadot-js/types?path=packages/primitives-codec)
|
||||
[](https://david-dm.org/polkadot-js/types?path=packages/primitives-codec#info=devDependencies)
|
||||
|
||||
# @polkadot/primitives-codec
|
||||
|
||||
Conversion of Polkadot types into `Uint8Array` values ready for inputs into the runtime.
|
||||
43
packages/code-primitives/package.json
Normal file
43
packages/code-primitives/package.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "@polkadot/primitives-codec",
|
||||
"version": "0.25.0",
|
||||
"description": "Encoding for primitives as runtime execution inputs",
|
||||
"main": "index.js",
|
||||
"engines": {
|
||||
"node": ">=6.4"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/polkadot-js/types.git"
|
||||
},
|
||||
"keywords": [
|
||||
"Polkadot"
|
||||
],
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"maintainers": [
|
||||
"Jaco Greeff <jacogr@gmail.com>"
|
||||
],
|
||||
"contributors": [],
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/polkadot-js/types/issues"
|
||||
},
|
||||
"homepage": "https://github.com/polkadot-js/types/tree/master/packages/primitives-codec#readme",
|
||||
"scripts": {
|
||||
"build": "polkadot-dev-build-babel",
|
||||
"check": "eslint src && flow check",
|
||||
"test": "echo \"Tests only available from root wrapper\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.0.0-beta.51",
|
||||
"@polkadot/primitives": "^0.25.0",
|
||||
"@polkadot/primitives-builder": "^0.25.0",
|
||||
"@polkadot/util": "^0.25.0",
|
||||
"@polkadot/util-crypto": "^0.25.0",
|
||||
"@polkadot/util-keyring": "^0.25.0"
|
||||
}
|
||||
}
|
||||
54
packages/code-primitives/src/block/decodeRaw.spec.js
Normal file
54
packages/code-primitives/src/block/decodeRaw.spec.js
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import extrinsics from '@polkadot/extrinsics';
|
||||
import encodeUnchecked from '@polkadot/extrinsics-codec/encode/unchecked';
|
||||
import hexToU8a from '@polkadot/util/hex/toU8a';
|
||||
import testingPairs from '@polkadot/util-keyring/testingPairs';
|
||||
|
||||
import decode from './decodeRaw';
|
||||
|
||||
const keyring = testingPairs();
|
||||
|
||||
describe('decodeRaw', () => {
|
||||
it('encodes the block properly', () => {
|
||||
expect(
|
||||
decode(
|
||||
hexToU8a(
|
||||
'0x' +
|
||||
// parent_hash
|
||||
'0900000000000000000000000000000000000000000000000000000000000009' +
|
||||
// number
|
||||
'4300000000000000' +
|
||||
// state_root
|
||||
'0800000000000000000000000000000000000000000000000000000000000008' +
|
||||
// transaction_root
|
||||
'0700000000000000000000000000000000000000000000000000000000000007' +
|
||||
// digest
|
||||
'02000000' +
|
||||
'0100000001' +
|
||||
'0100000002' +
|
||||
// transactions
|
||||
'01000000' +
|
||||
'6f000000' +
|
||||
// prefix
|
||||
'ff' +
|
||||
'0000000000000000000000000000000000000000000000000000000000000000' +
|
||||
'00000000' +
|
||||
'0300' +
|
||||
'7527000000000000' +
|
||||
'0000000000000000000000000000000000000000000000000000000000000000' +
|
||||
'0000000000000000000000000000000000000000000000000000000000000000'
|
||||
)
|
||||
)
|
||||
).toMatchObject({
|
||||
extrinsics: [
|
||||
encodeUnchecked(keyring.nobody, 0)(
|
||||
extrinsics.timestamp.public.set,
|
||||
[10101]
|
||||
)
|
||||
]
|
||||
});
|
||||
});
|
||||
});
|
||||
39
packages/code-primitives/src/block/decodeRaw.ts
Normal file
39
packages/code-primitives/src/block/decodeRaw.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import decodeExtrinsic from '@polkadot/extrinsics-codec/decode/length';
|
||||
import u8aToBn from '@polkadot/util/u8a/toBn';
|
||||
|
||||
import decodeHeader from '../header/decodeRaw';
|
||||
|
||||
type RawData = {
|
||||
body: Uint8Array,
|
||||
extrinsics: Array<Uint8Array>,
|
||||
header: Uint8Array,
|
||||
number: BN
|
||||
};
|
||||
|
||||
export default function decodeRaw (u8a: Uint8Array): RawData {
|
||||
const { body, header, number } = decodeHeader(u8a);
|
||||
const length = u8aToBn(body.subarray(0, 4), true).toNumber();
|
||||
const extrinsics = [];
|
||||
|
||||
for (let index = 0, offset = 4; index < length; index++) {
|
||||
const extrinsic = decodeExtrinsic(
|
||||
body.subarray(offset)
|
||||
);
|
||||
|
||||
offset += extrinsic.length + 4;
|
||||
extrinsics.push(extrinsic);
|
||||
}
|
||||
|
||||
return {
|
||||
body,
|
||||
extrinsics,
|
||||
header,
|
||||
number
|
||||
};
|
||||
}
|
||||
46
packages/code-primitives/src/block/encode.spec.js
Normal file
46
packages/code-primitives/src/block/encode.spec.js
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import extrinsics from '@polkadot/extrinsics';
|
||||
import encodeUnchecked from '@polkadot/extrinsics-codec/encode/unchecked';
|
||||
import blockBuilder from '@polkadot/primitives-builder/block';
|
||||
import hexToU8a from '@polkadot/util/hex/toU8a';
|
||||
import testingPairs from '@polkadot/util-keyring/testingPairs';
|
||||
|
||||
import { encodeBlock } from './index';
|
||||
|
||||
const keyring = testingPairs();
|
||||
|
||||
describe('encodeBlock', () => {
|
||||
it('encodes a block correctly (actual values)', () => {
|
||||
expect(
|
||||
encodeBlock(
|
||||
blockBuilder({
|
||||
header: {
|
||||
number: 9,
|
||||
parentHash: hexToU8a('0x737d699e4e42f78dc2fb098f01bb85389f2c7f0a77bb41918adac6bfa5b3ee46'),
|
||||
stateRoot: hexToU8a('0xf707774183723f201b875024069f30e7089b7f83c3c3cdc534b10d15fca91262')
|
||||
},
|
||||
extrinsics: [
|
||||
encodeUnchecked(keyring.nobody, 0)(
|
||||
extrinsics.timestamp.public.set,
|
||||
[0x5b13c3a4]
|
||||
),
|
||||
encodeUnchecked(keyring.nobody, 0)(
|
||||
extrinsics.parachains.public.setHeads,
|
||||
[[]]
|
||||
)
|
||||
]
|
||||
})
|
||||
)
|
||||
).toEqual(
|
||||
new Uint8Array([
|
||||
115, 125, 105, 158, 78, 66, 247, 141, 194, 251, 9, 143, 1, 187, 133, 56, 159, 44, 127, 10, 119, 187, 65, 145, 138, 218, 198, 191, 165, 179, 238, 70, 9, 0, 0, 0, 0, 0, 0, 0, 247, 7, 119, 65, 131, 114, 63, 32, 27, 135, 80, 36, 6, 159, 48, 231, 8, 155, 127, 131, 195, 195, 205, 197, 52, 177, 13, 21, 252, 169, 18, 98, 140, 102, 133, 98, 214, 123, 73, 173, 122, 252, 247, 48, 181, 86, 77, 188, 213, 161, 17, 19, 73, 96, 158, 181, 249, 69, 97, 15, 186, 12, 45, 157, 0, 0, 0, 0, 2, 0, 0, 0, 111, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 164, 195, 19, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
])
|
||||
// hexToU8a(
|
||||
// '0x737d699e4e42f78dc2fb098f01bb85389f2c7f0a77bb41918adac6bfa5b3ee460900000000000000f707774183723f201b875024069f30e7089b7f83c3c3cdc534b10d15fca91262ab602f7974bbfb513f021f39777e2195094dc64a2c1b7c82a1781cb9fd4768a800000000020000006e0000000000000000000000000000000000000000000000000000000000000000000000000000000300a4c3135b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||
// )
|
||||
);
|
||||
});
|
||||
});
|
||||
15
packages/code-primitives/src/block/encode.ts
Normal file
15
packages/code-primitives/src/block/encode.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Block } from '@polkadot/primitives/block';
|
||||
|
||||
import headerEncode from '../header/encode';
|
||||
import encodeRaw from './encodeRaw';
|
||||
|
||||
export default function encodeBlock ({ extrinsics, header }: Block): Uint8Array {
|
||||
return encodeRaw(
|
||||
headerEncode(header, extrinsics),
|
||||
extrinsics
|
||||
);
|
||||
}
|
||||
37
packages/code-primitives/src/block/encodeRaw.spec.js
Normal file
37
packages/code-primitives/src/block/encodeRaw.spec.js
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import encodeRaw from './encodeRaw';
|
||||
|
||||
describe('encodeRaw', () => {
|
||||
it('encodes correctly (actual values)', () => {
|
||||
expect(
|
||||
encodeRaw(
|
||||
new Uint8Array([
|
||||
168, 135, 224, 93, 140, 222, 226, 83, 13, 116, 138, 197, 164, 6, 48, 190, 101, 18, 221, 166, 40, 179, 158, 112, 133, 154, 215, 198, 177, 76, 212, 228,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
159, 216, 180, 61, 159, 12, 131, 80, 22, 196, 220, 94, 6, 222, 68, 159, 97, 60, 16, 69, 163, 149, 125, 138, 175, 36, 30, 93, 235, 4, 1, 168,
|
||||
245, 208, 141, 24, 250, 136, 158, 84, 67, 170, 59, 146, 17, 149, 62, 67, 254, 66, 126, 53, 20, 146, 252, 243, 137, 89, 224, 145, 252, 79, 109, 15,
|
||||
0, 0, 0, 0
|
||||
]),
|
||||
[
|
||||
new Uint8Array([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 188, 29, 21, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
]),
|
||||
new Uint8Array([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
])
|
||||
]
|
||||
)
|
||||
).toEqual(
|
||||
new Uint8Array([
|
||||
168, 135, 224, 93, 140, 222, 226, 83, 13, 116, 138, 197, 164, 6, 48, 190, 101, 18, 221, 166, 40, 179, 158, 112, 133, 154, 215, 198, 177, 76, 212, 228, 1, 0, 0, 0, 0, 0, 0, 0, 159, 216, 180, 61, 159, 12, 131, 80, 22, 196, 220, 94, 6, 222, 68, 159, 97, 60, 16, 69, 163, 149, 125, 138, 175, 36, 30, 93, 235, 4, 1, 168, 245, 208, 141, 24, 250, 136, 158, 84, 67, 170, 59, 146, 17, 149, 62, 67, 254, 66, 126, 53, 20, 146, 252, 243, 137, 89, 224, 145, 252, 79, 109, 15, 0, 0, 0, 0, 2, 0, 0, 0,
|
||||
110, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 188, 29, 21, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
106, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
])
|
||||
);
|
||||
});
|
||||
});
|
||||
19
packages/code-primitives/src/block/encodeRaw.ts
Normal file
19
packages/code-primitives/src/block/encodeRaw.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { UncheckedRaw } from '@polkadot/primitives/extrinsic';
|
||||
|
||||
import uncheckedLength from '@polkadot/extrinsics-codec/encode/length';
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
|
||||
import encodeArray from '../encoder/array';
|
||||
|
||||
export default function encodeBlockRaw (header: Uint8Array, extrinsics: Array<UncheckedRaw> = []): Uint8Array {
|
||||
return u8aConcat(
|
||||
header,
|
||||
encodeArray(
|
||||
extrinsics.map(uncheckedLength)
|
||||
)
|
||||
);
|
||||
}
|
||||
9
packages/code-primitives/src/block/index.ts
Normal file
9
packages/code-primitives/src/block/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import encodeBlock from './encode';
|
||||
|
||||
export {
|
||||
encodeBlock
|
||||
};
|
||||
37
packages/code-primitives/src/decoder/array.spec.js
Normal file
37
packages/code-primitives/src/decoder/array.spec.js
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import decodeArray from './array';
|
||||
|
||||
describe('decodeArray', () => {
|
||||
it('decodes an array with the length', () => {
|
||||
expect(
|
||||
decodeArray(
|
||||
new Uint8Array([
|
||||
2, 0, 0, 0, // length
|
||||
1, 2, // first
|
||||
3, 4 // second
|
||||
])
|
||||
)
|
||||
).toEqual({
|
||||
length: 2,
|
||||
data: new Uint8Array([1, 2, 3, 4])
|
||||
});
|
||||
});
|
||||
|
||||
it('decodes where array is an subarray', () => {
|
||||
expect(
|
||||
decodeArray(
|
||||
new Uint8Array([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // padding
|
||||
1, 0, 0, 0, // length
|
||||
1, 2, 3, 4 // entry
|
||||
]).subarray(8)
|
||||
)
|
||||
).toEqual({
|
||||
length: 1,
|
||||
data: new Uint8Array([1, 2, 3, 4])
|
||||
});
|
||||
});
|
||||
});
|
||||
18
packages/code-primitives/src/decoder/array.ts
Normal file
18
packages/code-primitives/src/decoder/array.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import u8aToBn from '@polkadot/util/u8a/toBn';
|
||||
|
||||
type DecodedArray = {
|
||||
length: number,
|
||||
data: Uint8Array
|
||||
};
|
||||
|
||||
export default function decodeArray (input: Uint8Array): DecodedArray {
|
||||
return {
|
||||
// FIXME: This conversion is horrible, however Dataview on subarray yields wrong getUint32 value
|
||||
length: u8aToBn(input.subarray(0, 4), true).toNumber(),
|
||||
data: input.slice(4)
|
||||
};
|
||||
}
|
||||
36
packages/code-primitives/src/decoder/u8a.spec.js
Normal file
36
packages/code-primitives/src/decoder/u8a.spec.js
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import decodeU8a from './u8a';
|
||||
|
||||
describe('decodeU8a', () => {
|
||||
it('decodes an input with the length', () => {
|
||||
expect(
|
||||
decodeU8a(
|
||||
new Uint8Array([
|
||||
4, 0, 0, 0, // length
|
||||
1, 2, 3, 4, // data
|
||||
5, 5, 5, 5 // extra
|
||||
])
|
||||
)
|
||||
).toEqual(
|
||||
new Uint8Array([1, 2, 3, 4])
|
||||
);
|
||||
});
|
||||
|
||||
it('decodes an subarray', () => {
|
||||
expect(
|
||||
decodeU8a(
|
||||
new Uint8Array([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // padding
|
||||
4, 0, 0, 0, // length
|
||||
1, 2, 3, 4, // data
|
||||
5, 5, 5, 5 // extra
|
||||
]).subarray(8)
|
||||
)
|
||||
).toEqual(
|
||||
new Uint8Array([1, 2, 3, 4])
|
||||
);
|
||||
});
|
||||
});
|
||||
12
packages/code-primitives/src/decoder/u8a.ts
Normal file
12
packages/code-primitives/src/decoder/u8a.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import u8aToBn from '@polkadot/util/u8a/toBn';
|
||||
|
||||
export default function decodeU8a (input: Uint8Array): Uint8Array {
|
||||
// FIXME: This conversion is horrible, however Dataview on subarray yields wrong getUint32 value
|
||||
const length = u8aToBn(input.subarray(0, 4), true).toNumber();
|
||||
|
||||
return input.slice(4, 4 + length);
|
||||
}
|
||||
22
packages/code-primitives/src/encoder/array.spec.js
Normal file
22
packages/code-primitives/src/encoder/array.spec.js
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import encodeArray from './array';
|
||||
|
||||
describe('encodeArray', () => {
|
||||
it('encodes an array with the length', () => {
|
||||
expect(
|
||||
encodeArray([
|
||||
new Uint8Array([1, 2]),
|
||||
new Uint8Array([3, 4])
|
||||
])
|
||||
).toEqual(
|
||||
new Uint8Array([
|
||||
2, 0, 0, 0, // length
|
||||
1, 2, // first
|
||||
3, 4 // second
|
||||
])
|
||||
);
|
||||
});
|
||||
});
|
||||
18
packages/code-primitives/src/encoder/array.ts
Normal file
18
packages/code-primitives/src/encoder/array.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
export default function encodeArray (input: Array<Uint8Array>): Uint8Array {
|
||||
const total = input.reduce((total, input) => total + input.length, 0);
|
||||
const output = new Uint8Array(total + 4);
|
||||
let offset = 4;
|
||||
|
||||
new DataView(output.buffer).setUint32(0, input.length, true);
|
||||
|
||||
return input.reduce((output, input) => {
|
||||
output.set(input, offset);
|
||||
offset += input.length;
|
||||
|
||||
return output;
|
||||
}, output);
|
||||
}
|
||||
20
packages/code-primitives/src/encoder/u8a.spec.js
Normal file
20
packages/code-primitives/src/encoder/u8a.spec.js
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import encodeU8a from './u8a';
|
||||
|
||||
describe('encodeU8a', () => {
|
||||
it('encodes an input with the length', () => {
|
||||
expect(
|
||||
encodeU8a(
|
||||
new Uint8Array([1, 2, 3, 4])
|
||||
)
|
||||
).toEqual(
|
||||
new Uint8Array([
|
||||
4, 0, 0, 0, // length
|
||||
1, 2, 3, 4 // data
|
||||
])
|
||||
);
|
||||
});
|
||||
});
|
||||
13
packages/code-primitives/src/encoder/u8a.ts
Normal file
13
packages/code-primitives/src/encoder/u8a.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
export default function encodeU8a (input: Uint8Array): Uint8Array {
|
||||
const output = new Uint8Array(input.length + 4);
|
||||
|
||||
new DataView(output.buffer).setUint32(0, input.length, true);
|
||||
|
||||
output.set(input, 4);
|
||||
|
||||
return output;
|
||||
}
|
||||
47
packages/code-primitives/src/header/decode.spec.js
Normal file
47
packages/code-primitives/src/header/decode.spec.js
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import createHeader from '@polkadot/primitives-builder/header';
|
||||
|
||||
import { decodeHeader } from './index';
|
||||
|
||||
describe('decodeHeader', () => {
|
||||
it('decodes properly', () => {
|
||||
expect(
|
||||
JSON.stringify(
|
||||
decodeHeader(
|
||||
new Uint8Array([
|
||||
// parent_hash
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
|
||||
// number
|
||||
67, 0, 0, 0, 0, 0, 0, 0,
|
||||
// state_root
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
|
||||
// transaction_root
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,
|
||||
// digest (length, log1, log2)
|
||||
2, 0, 0, 0,
|
||||
1, 0, 0, 0, 1,
|
||||
1, 0, 0, 0, 2
|
||||
])
|
||||
)
|
||||
)
|
||||
).toEqual(
|
||||
JSON.stringify(
|
||||
createHeader({
|
||||
digest: {
|
||||
logs: [
|
||||
new Uint8Array([1]),
|
||||
new Uint8Array([2])
|
||||
]
|
||||
},
|
||||
extrinsicsRoot: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6]),
|
||||
number: 67,
|
||||
parentHash: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5]),
|
||||
stateRoot: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3])
|
||||
})
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
24
packages/code-primitives/src/header/decode.ts
Normal file
24
packages/code-primitives/src/header/decode.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Header } from '@polkadot/primitives/header';
|
||||
|
||||
import createHeader from '@polkadot/primitives-builder/header';
|
||||
|
||||
import decodeRaw from './decodeRaw';
|
||||
import { OFF_PARENT_HASH, OFF_STATE_ROOT, OFF_TX_ROOT } from './offsets';
|
||||
|
||||
export default function decodeHeader (u8a: Uint8Array): Header {
|
||||
const { number, logs } = decodeRaw(u8a);
|
||||
|
||||
return createHeader({
|
||||
digest: {
|
||||
logs
|
||||
},
|
||||
extrinsicsRoot: u8a.subarray(OFF_TX_ROOT, OFF_TX_ROOT + 32),
|
||||
number,
|
||||
parentHash: u8a.subarray(OFF_PARENT_HASH, OFF_PARENT_HASH + 32),
|
||||
stateRoot: u8a.subarray(OFF_STATE_ROOT, OFF_STATE_ROOT + 32)
|
||||
});
|
||||
}
|
||||
57
packages/code-primitives/src/header/decodeRaw.spec.js
Normal file
57
packages/code-primitives/src/header/decodeRaw.spec.js
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import decode from './decodeRaw';
|
||||
|
||||
describe('decodeRaw', () => {
|
||||
it('returns the raw parts', () => {
|
||||
expect(
|
||||
JSON.stringify(
|
||||
decode(
|
||||
new Uint8Array([
|
||||
// parent_hash
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
|
||||
// number
|
||||
67, 0, 0, 0, 0, 0, 0, 0,
|
||||
// state_root
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
|
||||
// transaction_root
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,
|
||||
// digest (length, log1, log2)
|
||||
2, 0, 0, 0,
|
||||
1, 0, 0, 0, 1,
|
||||
1, 0, 0, 0, 2,
|
||||
// remainder
|
||||
1, 2, 3, 4, 5, 4, 3, 2, 1
|
||||
])
|
||||
)
|
||||
)
|
||||
).toEqual(
|
||||
JSON.stringify({
|
||||
body: new Uint8Array([1, 2, 3, 4, 5, 4, 3, 2, 1]),
|
||||
header: new Uint8Array([
|
||||
// parent_hash
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
|
||||
// number
|
||||
67, 0, 0, 0, 0, 0, 0, 0,
|
||||
// state_root
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
|
||||
// transaction_root
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,
|
||||
// digest (length, log1, log2)
|
||||
2, 0, 0, 0,
|
||||
1, 0, 0, 0, 1,
|
||||
1, 0, 0, 0, 2
|
||||
]),
|
||||
logs: [
|
||||
new Uint8Array([1]),
|
||||
new Uint8Array([2])
|
||||
],
|
||||
number: new BN(67)
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
39
packages/code-primitives/src/header/decodeRaw.ts
Normal file
39
packages/code-primitives/src/header/decodeRaw.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import u8aToBn from '@polkadot/util/u8a/toBn';
|
||||
|
||||
import decodeArray from '../decoder/array';
|
||||
import decodeU8a from '../decoder/u8a';
|
||||
import { OFF_DIGEST, OFF_NUMBER } from './offsets';
|
||||
|
||||
type DecodedRaw = {
|
||||
body: Uint8Array,
|
||||
header: Uint8Array,
|
||||
logs: Array<Uint8Array>,
|
||||
number: BN
|
||||
};
|
||||
|
||||
export default function decodeHeader (u8a: Uint8Array): DecodedRaw {
|
||||
const logs = [];
|
||||
const dd = decodeArray(u8a.subarray(OFF_DIGEST));
|
||||
let offset = 0;
|
||||
|
||||
for (let index = 0; index < dd.length; index++) {
|
||||
const log = decodeU8a(dd.data.subarray(offset));
|
||||
|
||||
logs.push(log);
|
||||
|
||||
offset += log.length + 4;
|
||||
}
|
||||
|
||||
return {
|
||||
body: dd.data.subarray(offset),
|
||||
header: u8a.subarray(0, OFF_DIGEST + offset + 4),
|
||||
logs,
|
||||
number: u8aToBn(u8a.subarray(OFF_NUMBER, OFF_NUMBER + 8), true)
|
||||
};
|
||||
}
|
||||
45
packages/code-primitives/src/header/encode.spec.js
Normal file
45
packages/code-primitives/src/header/encode.spec.js
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { encodeHeader } from './index';
|
||||
|
||||
describe('encodeHeader', () => {
|
||||
it('encodes the block header as u8a', () => {
|
||||
expect(
|
||||
encodeHeader({
|
||||
digest: {
|
||||
logs: [
|
||||
new Uint8Array([1, 2, 3]),
|
||||
new Uint8Array([7, 8, 9, 10])
|
||||
]
|
||||
},
|
||||
extrinsicsRoot: new Uint8Array([
|
||||
6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0
|
||||
]),
|
||||
parentHash: new Uint8Array([
|
||||
5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0
|
||||
]),
|
||||
number: 67,
|
||||
stateRoot: new Uint8Array([
|
||||
3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0
|
||||
])
|
||||
})
|
||||
).toEqual(
|
||||
new Uint8Array([
|
||||
// parentHash
|
||||
5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0,
|
||||
// number
|
||||
67, 0, 0, 0, 0, 0, 0, 0,
|
||||
// stateRoot
|
||||
3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0,
|
||||
// extrinsicsRoot
|
||||
6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0,
|
||||
// digest (length, log1, log2)
|
||||
2, 0, 0, 0,
|
||||
3, 0, 0, 0, 1, 2, 3,
|
||||
4, 0, 0, 0, 7, 8, 9, 10
|
||||
])
|
||||
);
|
||||
});
|
||||
});
|
||||
32
packages/code-primitives/src/header/encode.ts
Normal file
32
packages/code-primitives/src/header/encode.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { UncheckedRaw } from '@polkadot/primitives/extrinsic';
|
||||
import { Header } from '@polkadot/primitives/header';
|
||||
|
||||
import rootRaw from '@polkadot/primitives-builder/extrinsic/rootRaw';
|
||||
import bnToU8a from '@polkadot/util/bn/toU8a';
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
import u8aToU8a from '@polkadot/util/u8a/toU8a';
|
||||
|
||||
import encodeArray from '../encoder/array';
|
||||
import encodeU8a from '../encoder/u8a';
|
||||
|
||||
export default function encodeHeader ({ digest: { logs }, extrinsicsRoot, parentHash, number, stateRoot }: Header, extrinsics?: Array<UncheckedRaw>): Uint8Array {
|
||||
return u8aConcat(
|
||||
u8aToU8a(parentHash),
|
||||
bnToU8a(number, 64, true),
|
||||
u8aToU8a(stateRoot),
|
||||
extrinsics
|
||||
? rootRaw(extrinsics)
|
||||
: u8aToU8a(extrinsicsRoot),
|
||||
encodeArray(
|
||||
logs.map((log) =>
|
||||
encodeU8a(
|
||||
u8aToU8a(log)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
16
packages/code-primitives/src/header/hash.ts
Normal file
16
packages/code-primitives/src/header/hash.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Header } from '@polkadot/primitives/header';
|
||||
|
||||
import blake2Asu8a from '@polkadot/util-crypto/blake2/asU8a';
|
||||
|
||||
import encode from './encode';
|
||||
|
||||
export default function headerHash (header: Header): Uint8Array {
|
||||
return blake2Asu8a(
|
||||
encode(header),
|
||||
256
|
||||
);
|
||||
}
|
||||
11
packages/code-primitives/src/header/index.ts
Normal file
11
packages/code-primitives/src/header/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import decodeHeader from './decode';
|
||||
import encodeHeader from './encode';
|
||||
|
||||
export {
|
||||
decodeHeader,
|
||||
encodeHeader
|
||||
};
|
||||
17
packages/code-primitives/src/header/offsets.ts
Normal file
17
packages/code-primitives/src/header/offsets.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
const OFF_PARENT_HASH = 0;
|
||||
const OFF_NUMBER = OFF_PARENT_HASH + 32;
|
||||
const OFF_STATE_ROOT = OFF_NUMBER + 8;
|
||||
const OFF_TX_ROOT = OFF_STATE_ROOT + 32;
|
||||
const OFF_DIGEST = OFF_TX_ROOT + 32;
|
||||
|
||||
export {
|
||||
OFF_PARENT_HASH,
|
||||
OFF_NUMBER,
|
||||
OFF_STATE_ROOT,
|
||||
OFF_TX_ROOT,
|
||||
OFF_DIGEST
|
||||
};
|
||||
6
packages/code-primitives/src/index.ts
Normal file
6
packages/code-primitives/src/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
// Copyright 2017-2018 @polkadot/primitives-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
export * from './block';
|
||||
export * from './header';
|
||||
373
packages/trie-db/LICENSE
Normal file
373
packages/trie-db/LICENSE
Normal file
@@ -0,0 +1,373 @@
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
||||
30
packages/trie-db/README.md
Normal file
30
packages/trie-db/README.md
Normal file
@@ -0,0 +1,30 @@
|
||||
[](https://polkadot.js.org)
|
||||

|
||||
[](https://github.com/Flet/semistandard)
|
||||
[](https://www.npmjs.com/package/@polkadot/trie-db)
|
||||
[](https://travis-ci.org/polkadot-js/trie)
|
||||
[](https://codeclimate.com/github/polkadot-js/trie/maintainability)
|
||||
[](https://coveralls.io/github/polkadot-js/trie?branch=master)
|
||||
[](https://david-dm.org/polkadot-js/trie?path=packages/trie-db)
|
||||
[](https://david-dm.org/polkadot-js/trie?path=packages/trie-db#info=devDependencies)
|
||||
|
||||
# @polkadot/trie-db
|
||||
|
||||
An Implementation of the [Ethereum Merkle Patricia Tree](https://github.com/ethereum/wiki/wiki/Patricia-Tree) that uses Blake2 for hashing.
|
||||
|
||||
# Adapted from Ethereum
|
||||
|
||||
The has been adapted from the [original EthereumJs implementation](https://github.com/ethereumjs/merkle-patricia-tree) with the following changes -
|
||||
|
||||
- Introduce [TypeScript](https://www.typescriptlang.org/) into the mix
|
||||
- ES6-ify as applicable (Classes, `self` -> `this`, `function() {}` -> `() => {}`)
|
||||
- Moves to a Promise-based interface (as applicable)
|
||||
- Support only Uint8Array key/values (Buffer/String in the original)
|
||||
- Use utilities from [@polkadot/util](https://github.com/polkadot-js/common)
|
||||
- Supports blake2 hashing (sha3 in the original), aligning with the Polkadot tech stack)
|
||||
- Updated the build steps with sources moved to [src/](src/)
|
||||
- Tests updated to use [Jest](https://facebook.github.io/jest/)
|
||||
- Upgrade interfaces to latest [levelup](https://github.com/Level/levelup)
|
||||
- Removed the secure interface (not applicable for Substrate chains)
|
||||
|
||||
... well at least the above is the _idea_ behind the fork ...
|
||||
47
packages/trie-db/package.json
Normal file
47
packages/trie-db/package.json
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "@polkadot/trie-db",
|
||||
"version": "0.25.0",
|
||||
"description": "This is an implementation of the modified merkle patricia tree as speficed in Ethereum's yellow paper, adpated for Polkadot.",
|
||||
"main": "index.js",
|
||||
"scripts": {},
|
||||
"maintainers": [
|
||||
"Jaco Greeff <jacogr@gmail.com>"
|
||||
],
|
||||
"contributors": [
|
||||
"mjbecze <mjbecze@gmail.com>",
|
||||
"Aaron Kumavis <http://aaron.kumavis.me/> (https://github.com/kumavis)"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/polkadot-js/common.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/polkadot-js/common/issues"
|
||||
},
|
||||
"keywords": [
|
||||
"merkle",
|
||||
"radix",
|
||||
"trie",
|
||||
"ethereum"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.0.0-beta.51",
|
||||
"@polkadot/trie-hash": "^0.25.0",
|
||||
"@polkadot/util": "^0.25.0",
|
||||
"@polkadot/util-crypto": "^0.25.0",
|
||||
"@polkadot/util-rlp": "^0.25.0",
|
||||
"@types/async": "^2.0.49",
|
||||
"@types/semaphore": "^1.1.0",
|
||||
"async": "^1.4.2",
|
||||
"encoding-down": "^5.0.3",
|
||||
"level-ws": "0.1.0",
|
||||
"levelup": "^3.0.1",
|
||||
"memdown": "^3.0.0",
|
||||
"readable-stream": "^2.2.8",
|
||||
"semaphore": ">=1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ethereumjs-testing": "0.0.1"
|
||||
}
|
||||
}
|
||||
827
packages/trie-db/src/BaseTrie.ts
Normal file
827
packages/trie-db/src/BaseTrie.ts
Normal file
@@ -0,0 +1,827 @@
|
||||
// Copyright 2015-2018 authors & contributors of https://github.com/ethereumjs/merkle-patricia-tree
|
||||
// Copyright 2017-2018 @polkadot/trie-db authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the MPL-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { SemaphorePromise } from './types';
|
||||
|
||||
import async from 'async';
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
import levelup from 'levelup';
|
||||
import memdown from 'memdown';
|
||||
import logger from '@polkadot/util/logger';
|
||||
import assert from '@polkadot/util/assert';
|
||||
import isU8a from '@polkadot/util/is/u8a';
|
||||
import promisify from '@polkadot/util/promisify';
|
||||
import u8aToHex from '@polkadot/util/u8a/toHex';
|
||||
import decodeRlp from '@polkadot/util-rlp/decode';
|
||||
|
||||
import { EMPTY_ROOT_U8A, EMPTY_ROOT_STR } from './constants';
|
||||
import encoder from './encoder';
|
||||
import { nibblesMatchingLength, nibblesIsEqual, nibblesFromU8a } from './nibbles';
|
||||
import ReadStream from './streams/TrieRead';
|
||||
import nodeFactory from './nodeFactory';
|
||||
import isRawNode from './util/isRawNode';
|
||||
import prioritizedTaskExecutor from './util/taskExecutor';
|
||||
import semaphore from './util/semaphore';
|
||||
|
||||
type RawPutFn = (key: Uint8Array, value: Uint8Array) => Promise<any>;
|
||||
|
||||
const l = logger('trie/base');
|
||||
|
||||
export default class BaseTrie {
|
||||
// @ts-ignore we are assigning via this.root in constructor
|
||||
_root: Uint8Array;
|
||||
_getDBs: any[]; // FIXME
|
||||
_putDBs: any[]; // FIXME
|
||||
dbDown: any; // FIXME
|
||||
db: any; // FIXME
|
||||
putRaw: RawPutFn;
|
||||
semaphore: SemaphorePromise;
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
constructor (db, root: Uint8Array) {
|
||||
this.putRaw = this._putRaw;
|
||||
|
||||
this.semaphore = semaphore(1);
|
||||
this.dbDown = db || memdown();
|
||||
this.db = levelup(encoder(this.dbDown));
|
||||
this._getDBs = [this.db];
|
||||
this._putDBs = [this.db];
|
||||
this.root = root;
|
||||
|
||||
l.debug(() => ['Created BaseTrie', typeof db, u8aToHex(root)]);
|
||||
}
|
||||
|
||||
get root (): Uint8Array {
|
||||
return this._root;
|
||||
}
|
||||
|
||||
set root (value: Uint8Array) {
|
||||
if (value) {
|
||||
assert(isU8a(value) && value.length === 32, 'Invalid root length. Roots are Uint8Array 32 bytes');
|
||||
} else {
|
||||
value = EMPTY_ROOT_U8A;
|
||||
}
|
||||
|
||||
this._root = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value given a `key`
|
||||
* @method get
|
||||
* @param {Buffer|String} key - the key to search for
|
||||
* @param {Function} cb A callback `Function` which is given the arguments `err` - for errors that may have occured and `value` - the found value in a `Buffer` or if no value was found `null`
|
||||
*/
|
||||
async get (key: Uint8Array) {
|
||||
l.debug(() => ['get', 'key ->', u8aToHex(key)]);
|
||||
|
||||
const result = await this.findPath(key);
|
||||
|
||||
let value = null;
|
||||
|
||||
if (result && result.node && result.remainder.length === 0) {
|
||||
value = result.node.value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a given `value` at the given `key`
|
||||
* @method put
|
||||
* @param {Buffer|String} key
|
||||
* @param {Buffer|String} Value
|
||||
* @returns {Function} Promise<void>
|
||||
*/
|
||||
async put (key: Uint8Array, value: Uint8Array) {
|
||||
l.debug(() => ['put', 'key ->', u8aToHex(key), 'value ->', u8aToHex(value)]);
|
||||
|
||||
if (!value || value.toString() === '') {
|
||||
return this.del(key);
|
||||
}
|
||||
|
||||
return this.semaphore(async () => {
|
||||
if (this.root.toString() === EMPTY_ROOT_STR) {
|
||||
return this._createInitialNode(key, value); // if no root initialize this trie
|
||||
}
|
||||
|
||||
// first try to find the give key or its nearst node
|
||||
const result = await this.findPath(key);
|
||||
|
||||
return this._updateNode(key, value, result && result.remainder, result && result.stack);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes a value given a `key`
|
||||
* @method del
|
||||
* @param {Buffer|String} key
|
||||
* @param {Function} callback the callback `Function`
|
||||
*/
|
||||
del (key: Uint8Array) {
|
||||
l.debug(() => ['del', 'key ->', u8aToHex(key)]);
|
||||
|
||||
return this.semaphore(async () => {
|
||||
const result = await this.findPath(key);
|
||||
|
||||
if (result && result.node) {
|
||||
return this._deleteNode(key, result.stack);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a raw value in the underlying db
|
||||
* @method getRaw
|
||||
* @param {Buffer} key
|
||||
* @param {Function} callback A callback `Function`, which is given the arguments `err` - for errors that may have occured and `value` - the found value in a `Buffer` or if no value was found `null`.
|
||||
*/
|
||||
async getRaw (key: Uint8Array): Promise<Uint8Array> {
|
||||
let found: Uint8Array;
|
||||
|
||||
await Promise.all(
|
||||
this._getDBs.map(async (db) => {
|
||||
if (!found) {
|
||||
try {
|
||||
found = await db.get(key);
|
||||
} catch (error) {
|
||||
// l.error('getRaw', 'key ->', u8aToHex(key), error);
|
||||
// not doing anything
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
})
|
||||
);
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
return found;
|
||||
}
|
||||
|
||||
// retrieves a node from dbs by hash
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
async _lookupNode (node) {
|
||||
if (isRawNode(node)) {
|
||||
return nodeFactory.fromRaw(node);
|
||||
}
|
||||
|
||||
let value = await this.getRaw(node);
|
||||
|
||||
if (value) {
|
||||
try {
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
value = nodeFactory.fromRaw(decodeRlp(value));
|
||||
} catch (error) {
|
||||
l.error('_lookupNode decoding', typeof value, value);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// TODO: remove the proxy method when changing the caching
|
||||
async _putRaw (key: Uint8Array, value: Uint8Array) {
|
||||
return Promise.all(
|
||||
this._putDBs.map((db) => {
|
||||
return db.put(key, value);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a raw value in the underlying db
|
||||
* @method delRaw
|
||||
* @param {Buffer|String} key
|
||||
* @param {Function} callback A callback `Function`, which is given the argument `err` - for errors that may have occured
|
||||
*/
|
||||
delRaw (key: Uint8Array) {
|
||||
return Promise.all(
|
||||
this._putDBs.map((db) => {
|
||||
return db.del(key);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// writes a single node to dbs
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
_putNode (node) {
|
||||
const hash = node.hash();
|
||||
const serialized = node.serialize();
|
||||
|
||||
return this._putRaw(hash, serialized);
|
||||
}
|
||||
|
||||
// writes many nodes to db
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
_batchNodes (opStack) {
|
||||
return Promise.all(
|
||||
this._putDBs.map((db) => {
|
||||
return db.batch(opStack);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trys to find a path to the node for the given key
|
||||
* It returns a `stack` of nodes to the closet node
|
||||
* @method findPath
|
||||
* @param {String|Buffer} - key - the search key
|
||||
* @param {Function} - cb - the callback function. Its is given the following
|
||||
* arguments
|
||||
* - err - any errors encontered
|
||||
* - node - the last node found
|
||||
* - remainder - the remaining key nibbles not accounted for
|
||||
* - stack - an array of nodes that forms the path to node we are searching for
|
||||
*/
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
findPath (_targetKey) {
|
||||
const stack: any[] = []; // FIXME
|
||||
const targetKey = nibblesFromU8a(_targetKey);
|
||||
|
||||
l.debug(() => ['findPath', targetKey.join(', ')]);
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
const processNode = (nodeRef, node, keyProgress, walkController) => {
|
||||
const nodeKey = node.key || [];
|
||||
const remainder = targetKey.slice(nibblesMatchingLength(keyProgress, targetKey));
|
||||
const matchingLen = nibblesMatchingLength(remainder, nodeKey);
|
||||
|
||||
stack.push(node);
|
||||
|
||||
if (node.type === 'branch') {
|
||||
if (remainder.length === 0) {
|
||||
walkController.return(null, { node, remainder: [], stack });
|
||||
// we exhausted the key without finding a node
|
||||
} else {
|
||||
const branchIndex = remainder[0];
|
||||
const branchNode = node.getValue(branchIndex);
|
||||
|
||||
if (!branchNode) {
|
||||
// there are no more nodes to find and we didn't find the key
|
||||
walkController.return(null, { node: null, remainder, stack });
|
||||
} else {
|
||||
// node found, continuing search
|
||||
walkController.only(branchIndex);
|
||||
}
|
||||
}
|
||||
} else if (node.type === 'leaf') {
|
||||
if (nibblesIsEqual(remainder, nodeKey)) {
|
||||
// keys match, return node with empty key
|
||||
walkController.return(null, { node, remainder: [], stack });
|
||||
} else {
|
||||
// reached leaf but keys dont match
|
||||
walkController.return(null, { node: null, remainder, stack });
|
||||
}
|
||||
} else if (node.type === 'extention') {
|
||||
if (matchingLen !== nodeKey.length) {
|
||||
// keys dont match, fail
|
||||
walkController.return(null, { node: null, remainder, stack });
|
||||
} else {
|
||||
// keys match, continue search
|
||||
walkController.next();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return promisify(this, this._walkTrie, this.root, processNode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds all nodes that store k,v values
|
||||
*/
|
||||
// NOTE seems unused
|
||||
// _findNode = function (key, root, stack, cb) {
|
||||
// this.findPath(key, (...args) => {
|
||||
// cb.apply(null, args);
|
||||
// });
|
||||
// };
|
||||
|
||||
/*
|
||||
* Finds all nodes that store k,v values
|
||||
*/
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
_findValueNodes (onFound, cb) {
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
this._walkTrie(this.root, (nodeRef, node, key, walkController) => {
|
||||
let fullKey = key;
|
||||
|
||||
if (node.key) {
|
||||
fullKey = key.concat(node.key);
|
||||
}
|
||||
|
||||
if (node.type === 'leaf') {
|
||||
// found leaf node!
|
||||
onFound(nodeRef, node, fullKey, walkController.next);
|
||||
} else if (node.type === 'branch' && node.value) {
|
||||
// found branch with value
|
||||
onFound(nodeRef, node, fullKey, walkController.next);
|
||||
} else {
|
||||
// keep looking for value nodes
|
||||
walkController.next();
|
||||
}
|
||||
}, cb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds all nodes that are stored directly in the db
|
||||
* (some nodes are stored raw inside other nodes)
|
||||
*/
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
_findDbNodes (onFound, cb) {
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
this._walkTrie(this.root, (nodeRef, node, key, walkController) => {
|
||||
if (isRawNode(nodeRef)) {
|
||||
walkController.next();
|
||||
} else {
|
||||
onFound(nodeRef, node, key, walkController.next);
|
||||
}
|
||||
}, cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a node
|
||||
* @method _updateNode
|
||||
* @param {Buffer} key
|
||||
* @param {Buffer| String} value
|
||||
* @param {Array} keyRemainder
|
||||
* @param {Array} stack -
|
||||
* @param {Function} cb - the callback
|
||||
*/
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
async _updateNode (key, value, keyRemainder, stack) {
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
const toSave = [];
|
||||
const lastNode = stack.pop();
|
||||
|
||||
// add the new nodes
|
||||
key = nibblesFromU8a(key);
|
||||
|
||||
// Check if the last node is a leaf and the key matches to this
|
||||
let matchLeaf = false;
|
||||
|
||||
if (lastNode.type === 'leaf') {
|
||||
let l = 0;
|
||||
|
||||
for (let i = 0; i < stack.length; i++) {
|
||||
const n = stack[i];
|
||||
|
||||
if (n.type === 'branch') {
|
||||
l++;
|
||||
} else {
|
||||
l += n.key.length;
|
||||
}
|
||||
}
|
||||
|
||||
if ((nibblesMatchingLength(lastNode.key, key.slice(l)) === lastNode.key.length) && (keyRemainder.length === 0)) {
|
||||
matchLeaf = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (matchLeaf) {
|
||||
// just updating a found value
|
||||
lastNode.value = value;
|
||||
stack.push(lastNode);
|
||||
} else if (lastNode.type === 'branch') {
|
||||
stack.push(lastNode);
|
||||
|
||||
if (keyRemainder !== 0) {
|
||||
// add an extention to a branch node
|
||||
keyRemainder.shift();
|
||||
// create a new leaf
|
||||
stack.push(nodeFactory.fromLeaf(keyRemainder, value));
|
||||
} else {
|
||||
lastNode.value = value;
|
||||
}
|
||||
} else {
|
||||
// create a branch node
|
||||
const lastKey = lastNode.key;
|
||||
const matchingLength = nibblesMatchingLength(lastKey, keyRemainder);
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
const newBranchNode = nodeFactory.fromBranch();
|
||||
|
||||
// create a new extention node
|
||||
if (matchingLength !== 0) {
|
||||
const newKey = lastNode.key.slice(0, matchingLength);
|
||||
const newExtNode = nodeFactory.fromExtention(newKey, value);
|
||||
|
||||
stack.push(newExtNode);
|
||||
lastKey.splice(0, matchingLength);
|
||||
keyRemainder.splice(0, matchingLength);
|
||||
}
|
||||
|
||||
stack.push(newBranchNode);
|
||||
|
||||
if (lastKey.length !== 0) {
|
||||
const branchKey = lastKey.shift();
|
||||
|
||||
if (lastKey.length !== 0 || lastNode.type === 'leaf') {
|
||||
// shriking extention or leaf
|
||||
lastNode.key = lastKey;
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
const formatedNode = this._formatNode(lastNode, false, toSave);
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
newBranchNode.setValue(branchKey, formatedNode);
|
||||
} else {
|
||||
// remove extention or attaching
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
this._formatNode(lastNode, false, true, toSave);
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
newBranchNode.setValue(branchKey, lastNode.value);
|
||||
}
|
||||
} else {
|
||||
newBranchNode.value = lastNode.value;
|
||||
}
|
||||
|
||||
if (keyRemainder.length !== 0) {
|
||||
keyRemainder.shift();
|
||||
|
||||
// add a leaf node to the new branch node
|
||||
stack.push(nodeFactory.fromLeaf(keyRemainder, value));
|
||||
} else {
|
||||
newBranchNode.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
return this._saveStack(key, stack, toSave);
|
||||
}
|
||||
|
||||
// walk tree
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
async _walkTrie (root, onNode, onDone) {
|
||||
root = root || this.root;
|
||||
|
||||
let isAborted: boolean = false;
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
let returnValues: any[] = [];
|
||||
|
||||
if (root.toString() === EMPTY_ROOT_STR) {
|
||||
onDone();
|
||||
return;
|
||||
}
|
||||
|
||||
// the maximum pool size should be high enough to utilise the parallelizability of reading nodes from disk and
|
||||
// low enough to utilize the prioritisation of node lookup.
|
||||
const maxPoolSize = 500;
|
||||
const taskExecutor = prioritizedTaskExecutor(maxPoolSize);
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
const processNode = (nodeRef, node, key, cb) => {
|
||||
if (!node || isAborted) {
|
||||
return cb();
|
||||
}
|
||||
|
||||
const self = this;
|
||||
let isStopped = false;
|
||||
|
||||
key = key || [];
|
||||
|
||||
const walkController = {
|
||||
stop: function () {
|
||||
isStopped = true;
|
||||
cb();
|
||||
},
|
||||
// end all traversal and return values to the onDone cb
|
||||
return: function () {
|
||||
isAborted = true;
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
returnValues = arguments;
|
||||
cb();
|
||||
},
|
||||
next: async function () {
|
||||
if (isAborted || isStopped) {
|
||||
return cb();
|
||||
}
|
||||
|
||||
const children = node.getChildren();
|
||||
|
||||
// @ts-ignore FIXME callback
|
||||
async.forEachOf(children, (childData: any[], index: number, cb) => {
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
const keyExtension = childData[0];
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
const childRef = childData[1];
|
||||
const childKey = key.concat(keyExtension);
|
||||
const priority = childKey.length;
|
||||
|
||||
taskExecutor(priority, async (taskCallback) => {
|
||||
const childNode = await self._lookupNode(childRef);
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
taskCallback();
|
||||
processNode(childRef, childNode, childKey, cb);
|
||||
});
|
||||
}, cb);
|
||||
},
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
only: function (childIndex) {
|
||||
const childRef = node.getValue(childIndex);
|
||||
const childKey = key.slice();
|
||||
|
||||
childKey.push(childIndex);
|
||||
|
||||
const priority = childKey.length;
|
||||
|
||||
taskExecutor(priority, async (taskCallback) => {
|
||||
const childNode = await self._lookupNode(childRef);
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
taskCallback();
|
||||
processNode(childRef, childNode, childKey, cb);
|
||||
});
|
||||
}
|
||||
};
|
||||
onNode(nodeRef, node, key, walkController);
|
||||
};
|
||||
|
||||
const node = await this._lookupNode(root);
|
||||
|
||||
processNode(root, node, null, (error: Error | null) => {
|
||||
if (error) {
|
||||
onDone(error);
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
onDone.apply(null, returnValues);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* saves a stack
|
||||
* @method _saveStack
|
||||
* @param {Array} key - the key. Should follow the stack
|
||||
* @param {Array} stack - a stack of nodes to the value given by the key
|
||||
* @param {Array} opStack - a stack of levelup operations to commit at the end of this funciton
|
||||
* @param {Function} cb
|
||||
*/
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
_saveStack (key, stack, opStack: any[]) {
|
||||
let lastRoot;
|
||||
|
||||
// update nodes
|
||||
while (stack.length) {
|
||||
const node = stack.pop();
|
||||
|
||||
if (node.type === 'leaf') {
|
||||
key.splice(key.length - node.key.length);
|
||||
} else if (node.type === 'extention') {
|
||||
key.splice(key.length - node.key.length);
|
||||
if (lastRoot) {
|
||||
node.value = lastRoot;
|
||||
}
|
||||
} else if (node.type === 'branch') {
|
||||
if (lastRoot) {
|
||||
const branchKey = key.pop();
|
||||
|
||||
node.setValue(branchKey, lastRoot);
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
lastRoot = this._formatNode(node, stack.length === 0, opStack);
|
||||
}
|
||||
|
||||
if (lastRoot) {
|
||||
this.root = lastRoot;
|
||||
}
|
||||
|
||||
return this._batchNodes(opStack);
|
||||
}
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
async _deleteNode (key: Uint8Array, stack) {
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
const processBranchNode = (key, branchKey, branchNode, parentNode, stack) => {
|
||||
// branchNode is the node ON the branch node not THE branch node
|
||||
const branchNodeKey = branchNode.key;
|
||||
|
||||
if (!parentNode || parentNode.type === 'branch') {
|
||||
// branch->?
|
||||
if (parentNode) {
|
||||
stack.push(parentNode);
|
||||
}
|
||||
|
||||
if (branchNode.type === 'branch') {
|
||||
// create an extention node
|
||||
// branch->extention->branch
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
stack.push(nodeFactory.fromExtention([branchKey], null));
|
||||
key.push(branchKey);
|
||||
} else {
|
||||
// branch key is an extention or a leaf
|
||||
// branch->(leaf or extention)
|
||||
branchNodeKey.unshift(branchKey);
|
||||
branchNode.key = branchNodeKey;
|
||||
|
||||
// hackery. This is equvilant to array.concat except we need keep the
|
||||
// rerfance to the `key` that was passed in.
|
||||
branchNodeKey.unshift(0);
|
||||
branchNodeKey.unshift(key.length);
|
||||
key.splice.apply(key, branchNodeKey);
|
||||
}
|
||||
stack.push(branchNode);
|
||||
} else {
|
||||
// parent is a extention
|
||||
let parentKey = parentNode.key;
|
||||
|
||||
if (branchNode.type === 'branch') {
|
||||
// ext->branch
|
||||
parentKey.push(branchKey);
|
||||
key.push(branchKey);
|
||||
parentNode.key = parentKey;
|
||||
stack.push(parentNode);
|
||||
} else {
|
||||
// branch node is an leaf or extention and parent node is an exstention
|
||||
// add two keys together
|
||||
// dont push the parent node
|
||||
branchNodeKey.unshift(branchKey);
|
||||
key = key.concat(branchNodeKey);
|
||||
parentKey = parentKey.concat(branchNodeKey);
|
||||
branchNode.key = parentKey;
|
||||
}
|
||||
stack.push(branchNode);
|
||||
}
|
||||
|
||||
return key;
|
||||
};
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
const opStack: any[] = [];
|
||||
let lastNode = stack.pop();
|
||||
let parentNode = stack.pop();
|
||||
|
||||
if (!Array.isArray(key)) {
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
key = nibblesFromU8a(key);
|
||||
}
|
||||
|
||||
if (!parentNode) {
|
||||
// the root here has to be a leaf.
|
||||
this.root = EMPTY_ROOT_U8A;
|
||||
} else {
|
||||
if (lastNode.type === 'branch') {
|
||||
lastNode.value = null;
|
||||
} else {
|
||||
// the lastNode has to be a leaf if its not a branch. And a leaf's parent
|
||||
// if it has one must be a branch.
|
||||
const lastNodeKey = lastNode.key;
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
key.splice(key.length - lastNodeKey.length);
|
||||
// delete the value
|
||||
this._formatNode(lastNode, false, true, opStack);
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
parentNode.setValue(key.pop(), null);
|
||||
lastNode = parentNode;
|
||||
parentNode = stack.pop();
|
||||
}
|
||||
|
||||
// nodes on the branch
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
const branchNodes = [];
|
||||
|
||||
// count the number of nodes on the branch
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
lastNode.raw.forEach(function (node, i) {
|
||||
const val = lastNode.getValue(i);
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
if (val) branchNodes.push([i, val]);
|
||||
});
|
||||
|
||||
// if there is only one branch node left, collapse the branch node
|
||||
if (branchNodes.length === 1) {
|
||||
// add the one remaing branch node to node above it
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
const branchNode = branchNodes[0][1];
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
const branchNodeKey = branchNodes[0][0];
|
||||
|
||||
// look up node
|
||||
const foundNode = await this._lookupNode(branchNode);
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
key = processBranchNode(key, branchNodeKey, foundNode, parentNode, stack, opStack);
|
||||
|
||||
return this._saveStack(key, stack, opStack);
|
||||
} else {
|
||||
// simple removing a leaf and recaluclation the stack
|
||||
if (parentNode) {
|
||||
stack.push(parentNode);
|
||||
}
|
||||
|
||||
stack.push(lastNode);
|
||||
|
||||
return this._saveStack(key, stack, opStack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Creates the initial node from an empty tree
|
||||
_createInitialNode (key: Uint8Array, value: Uint8Array) {
|
||||
const newNode = nodeFactory.fromLeaf(key, value);
|
||||
|
||||
this.root = newNode.hash();
|
||||
|
||||
return this._putNode(newNode);
|
||||
}
|
||||
|
||||
// formats node to be saved by levelup.batch.
|
||||
// returns either the hash that will be used key or the rawNode
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
_formatNode (node: any, topLevel: any, remove: any, opStack: any) {
|
||||
if (arguments.length === 3) {
|
||||
opStack = remove;
|
||||
remove = false;
|
||||
}
|
||||
|
||||
const rlpNode = node.serialize();
|
||||
|
||||
if (rlpNode.length >= 32 || topLevel) {
|
||||
const hashRoot = node.hash();
|
||||
|
||||
// FIXME Actually 2 things wrong here - this is on checkpoint, so one higher-level class...
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
if (remove && this.isCheckpoint) {
|
||||
opStack.push({
|
||||
type: 'del',
|
||||
key: hashRoot
|
||||
});
|
||||
} else {
|
||||
opStack.push({
|
||||
type: 'put',
|
||||
key: hashRoot,
|
||||
value: rlpNode
|
||||
});
|
||||
}
|
||||
|
||||
return hashRoot;
|
||||
}
|
||||
|
||||
return node.raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* The `data` event is given an `Object` hat has two properties; the `key` and the `value`. Both should be Buffers.
|
||||
* @method createReadStream
|
||||
* @return {stream.Readable} Returns a [stream](https://nodejs.org/dist/latest-v5.x/docs/api/stream.html#stream_class_stream_readable) of the contents of the `trie`
|
||||
*/
|
||||
createReadStream () {
|
||||
return new ReadStream(this);
|
||||
}
|
||||
|
||||
// creates a new trie backed by the same db
|
||||
// and starting at the same root
|
||||
copy () {
|
||||
l.debug(() => ['Copying BaseTrie', typeof this.dbDown, u8aToHex(this.root)]);
|
||||
|
||||
return new BaseTrie(this.dbDown, this.root);
|
||||
}
|
||||
|
||||
/**
|
||||
* The given hash of operations (key additions or deletions) are executed on the DB
|
||||
* @method batch
|
||||
* @example
|
||||
* const ops = [
|
||||
* { type: 'del', key: 'father' }
|
||||
* , { type: 'put', key: 'name', value: 'Yuri Irsenovich Kim' }
|
||||
* , { type: 'put', key: 'dob', value: '16 February 1941' }
|
||||
* , { type: 'put', key: 'spouse', value: 'Kim Young-sook' }
|
||||
* , { type: 'put', key: 'occupation', value: 'Clown' }
|
||||
* ]
|
||||
* trie.batch(ops)
|
||||
* @param {Array} ops
|
||||
* @param {Function} cb
|
||||
*/
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
batch (ops: any[]) {
|
||||
return Promise.all(
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
ops.map((op) => {
|
||||
if (op.type === 'put') {
|
||||
return this.put(op.key, op.value);
|
||||
} else if (op.type === 'del') {
|
||||
return this.del(op.key);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given root exists
|
||||
* @method checkRoot
|
||||
* @param {Buffer} root
|
||||
* @param {Function} cb
|
||||
*/
|
||||
async checkRoot (root: Uint8Array): Promise<boolean> {
|
||||
const value = await this._lookupNode(root);
|
||||
|
||||
return !!value;
|
||||
}
|
||||
}
|
||||
161
packages/trie-db/src/CheckpointTrie.ts
Normal file
161
packages/trie-db/src/CheckpointTrie.ts
Normal file
@@ -0,0 +1,161 @@
|
||||
// Copyright 2015-2018 authors & contributors of https://github.com/ethereumjs/merkle-patricia-tree
|
||||
// Copyright 2017-2018 @polkadot/trie-db authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the MPL-2.0 license. See the LICENSE file for details.
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
import levelws from 'level-ws';
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
import levelup from 'levelup';
|
||||
import memdown from 'memdown';
|
||||
import assert from '@polkadot/util/assert';
|
||||
import logger from '@polkadot/util/logger';
|
||||
import u8aToHex from '@polkadot/util/u8a/toHex';
|
||||
|
||||
import BaseTrie from './BaseTrie';
|
||||
import encoder from './encoder';
|
||||
import ScratchReadStream from './streams/ScratchRead';
|
||||
|
||||
const l = logger('trie/checkpt');
|
||||
|
||||
function putRaw (key: Uint8Array, value: Uint8Array) {
|
||||
return Promise.all(
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
this.__putDBs.map((db) => {
|
||||
return db.put(key, value);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
export default class CheckpointTrie extends BaseTrie {
|
||||
_checkpoints: Array<Uint8Array>;
|
||||
_scratch: any; // FIXME
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
__putDBs: any[]; // FIXME
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
constructor (db, root: Uint8Array) {
|
||||
super(db, root);
|
||||
|
||||
this._scratch = null;
|
||||
this._checkpoints = [];
|
||||
|
||||
l.debug(() => 'Created CheckpointTrie');
|
||||
}
|
||||
|
||||
get isCheckpoint () {
|
||||
return !!this._checkpoints.length;
|
||||
}
|
||||
|
||||
copy () {
|
||||
l.debug(() => ['Copying CheckpointTrie', typeof this.dbDown, u8aToHex(this.root)]);
|
||||
|
||||
return new CheckpointTrie(this.dbDown, this.root);
|
||||
}
|
||||
|
||||
async checkpoint () {
|
||||
l.debug(() => 'Marking checkpoint');
|
||||
|
||||
const wasCheckpoint = this.isCheckpoint;
|
||||
|
||||
this._checkpoints.push(this.root);
|
||||
|
||||
if (!wasCheckpoint && this.isCheckpoint) {
|
||||
this._enterCpMode();
|
||||
}
|
||||
}
|
||||
|
||||
commit () {
|
||||
l.debug(() => 'Committing checkpoint');
|
||||
|
||||
return this.semaphore(async () => {
|
||||
assert(this.isCheckpoint, 'trying to commit when not checkpointed');
|
||||
|
||||
this._checkpoints.pop();
|
||||
|
||||
if (this.isCheckpoint) {
|
||||
return;
|
||||
}
|
||||
|
||||
return this._exitCpMode(true);
|
||||
});
|
||||
}
|
||||
|
||||
revert () {
|
||||
l.debug(() => 'Reverting checkpoint');
|
||||
|
||||
return this.semaphore(async () => {
|
||||
if (!this.isCheckpoint) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.root = this._checkpoints.pop() as Uint8Array;
|
||||
|
||||
if (this.isCheckpoint) {
|
||||
return;
|
||||
}
|
||||
|
||||
return this._exitCpMode(false);
|
||||
});
|
||||
}
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
createScratchReadStream (scratch) {
|
||||
const trie = this.copy();
|
||||
|
||||
scratch = scratch || this._scratch;
|
||||
|
||||
// only read from the scratch
|
||||
trie._getDBs = [scratch];
|
||||
trie._scratch = scratch;
|
||||
|
||||
return new ScratchReadStream(trie);
|
||||
}
|
||||
|
||||
_enterCpMode () {
|
||||
l.debug(() => 'Entering checkpoint mode');
|
||||
|
||||
this._scratch = levelup(encoder(memdown()));
|
||||
|
||||
this._getDBs = [this._scratch].concat(this._getDBs);
|
||||
this.__putDBs = this._putDBs;
|
||||
this._putDBs = [this._scratch];
|
||||
this._putRaw = this.putRaw;
|
||||
this.putRaw = putRaw;
|
||||
}
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
_exitCpMode (commitState) {
|
||||
l.debug(() => 'Exiting checkpoint mode');
|
||||
|
||||
const scratch = this._scratch;
|
||||
this._scratch = null;
|
||||
this._getDBs = this._getDBs.slice(1);
|
||||
this._putDBs = this.__putDBs;
|
||||
this.putRaw = this._putRaw;
|
||||
|
||||
if (!commitState) {
|
||||
return;
|
||||
}
|
||||
|
||||
return Promise.all(
|
||||
this._putDBs.map((db) => {
|
||||
return new Promise((resolve) => {
|
||||
if (!db.createWriteStream) {
|
||||
db = levelws(db);
|
||||
}
|
||||
|
||||
this
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
.createScratchReadStream(scratch)
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
.pipe(
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
db.createWriteStream(encoder.options)
|
||||
)
|
||||
.on('close', resolve);
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
170
packages/trie-db/src/Node.ts
Normal file
170
packages/trie-db/src/Node.ts
Normal file
@@ -0,0 +1,170 @@
|
||||
// Copyright 2015-2018 authors & contributors of https://github.com/ethereumjs/merkle-patricia-tree
|
||||
// Copyright 2017-2018 @polkadot/trie-db authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the MPL-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { DecodedRlp, Trie$Node$Type } from './types';
|
||||
|
||||
import isU8a from '@polkadot/util/is/u8a';
|
||||
import u8aToHex from '@polkadot/util/u8a/toHex';
|
||||
import keccakAsU8a from '@polkadot/util-crypto/keccak/asU8a';
|
||||
import encodeRlp from '@polkadot/util-rlp/encode';
|
||||
|
||||
import nibblesFromU8a from './nibbles/fromU8a';
|
||||
import nibblesToU8a from './nibbles/toU8a';
|
||||
|
||||
function addHexPrefix (key: Array<number>, isTerminator: boolean): Array<number> {
|
||||
// odd
|
||||
if (key.length % 2) {
|
||||
key.unshift(1);
|
||||
} else {
|
||||
// even
|
||||
key.unshift(0);
|
||||
key.unshift(0);
|
||||
}
|
||||
|
||||
if (isTerminator) {
|
||||
key[0] += 2;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
function removeHexPrefix (key: Uint8Array): Uint8Array {
|
||||
return key[0] % 2
|
||||
? key.slice(1)
|
||||
: key.slice(2);
|
||||
}
|
||||
|
||||
export default class TrieNode {
|
||||
raw: DecodedRlp;
|
||||
type: Trie$Node$Type;
|
||||
|
||||
constructor (type: Trie$Node$Type, raw: DecodedRlp) {
|
||||
this.raw = raw;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
get value () {
|
||||
return this.getValue();
|
||||
}
|
||||
|
||||
set value (v) {
|
||||
this.setValue(v);
|
||||
}
|
||||
|
||||
get key () {
|
||||
return this.getKey();
|
||||
}
|
||||
|
||||
set key (k) {
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
this.setKey(k);
|
||||
}
|
||||
|
||||
setValue (key: number | Uint8Array, value?: Uint8Array) {
|
||||
if (this.type !== 'branch') {
|
||||
this.raw[1] = key as Uint8Array;
|
||||
return;
|
||||
}
|
||||
|
||||
if (arguments.length === 1) {
|
||||
value = key as Uint8Array;
|
||||
key = 16;
|
||||
}
|
||||
|
||||
this.raw[key as number] = value as Uint8Array;
|
||||
}
|
||||
|
||||
getValue (key?: number) {
|
||||
if (this.type !== 'branch') {
|
||||
return this.raw[1];
|
||||
}
|
||||
|
||||
if (arguments.length === 0) {
|
||||
key = 16;
|
||||
}
|
||||
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
const val = this.raw[key];
|
||||
|
||||
if (val !== null && val !== undefined && val.length !== 0) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
setKey (key: Array<number> | Uint8Array) {
|
||||
if (this.type !== 'branch') {
|
||||
if (Array.isArray(key)) {
|
||||
key = key.slice(0); // copy the key
|
||||
} else {
|
||||
key = nibblesFromU8a(key);
|
||||
}
|
||||
|
||||
key = addHexPrefix(key, this.type === 'leaf');
|
||||
this.raw[0] = nibblesToU8a(key);
|
||||
}
|
||||
}
|
||||
|
||||
getKey () {
|
||||
if (this.type !== 'branch') {
|
||||
return removeHexPrefix(
|
||||
// @ts-ignore FIXME, we need to properly check the full file
|
||||
nibblesFromU8a(this.raw[0])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
serialize (): Uint8Array {
|
||||
return encodeRlp(this.raw);
|
||||
}
|
||||
|
||||
hash (): Uint8Array {
|
||||
return keccakAsU8a(this.serialize());
|
||||
}
|
||||
|
||||
toString (): string {
|
||||
return this.raw.reduce((out, el, index) => {
|
||||
if (index !== 0) {
|
||||
out += ', ';
|
||||
}
|
||||
|
||||
if (isU8a(el)) {
|
||||
out += u8aToHex(el);
|
||||
} else if (el) {
|
||||
out += 'object';
|
||||
} else {
|
||||
out += 'empty';
|
||||
}
|
||||
|
||||
return out;
|
||||
}, `${this.type}: [`) + ']';
|
||||
}
|
||||
|
||||
getChildren () {
|
||||
const children = [];
|
||||
|
||||
switch (this.type) {
|
||||
case 'leaf':
|
||||
// no children
|
||||
break;
|
||||
case 'extention':
|
||||
// one child
|
||||
children.push([this.key, this.getValue()]);
|
||||
break;
|
||||
case 'branch':
|
||||
for (let index = 0, end = 16; index < end; index++) {
|
||||
const value = this.getValue(index);
|
||||
|
||||
if (value) {
|
||||
children.push([
|
||||
[index], value
|
||||
]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
}
|
||||
13
packages/trie-db/src/constants.ts
Normal file
13
packages/trie-db/src/constants.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2017-2018 @polkadot/trie-db authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the MPL-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import trieRoot from '@polkadot/trie-hash/root';
|
||||
|
||||
const EMPTY_ROOT_U8A = trieRoot([]);
|
||||
const EMPTY_ROOT_STR = EMPTY_ROOT_U8A.toString();
|
||||
|
||||
export {
|
||||
EMPTY_ROOT_U8A,
|
||||
EMPTY_ROOT_STR
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user