-
Notifications
You must be signed in to change notification settings - Fork 0
Passing the era #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 11 commits
67625a0
80f587d
9fb26b5
80f1486
6f7efd4
c5130df
a500fd1
c36cb9d
eaf0f3e
bb443f6
49139f7
f654f3c
db2b56e
b32ef44
14e9825
60d88ef
09d5c25
1a3931d
48da3e8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| // Copyright 2017-2019 @polkadot/types authors & contributors | ||
| // This software may be modified and distributed under the terms | ||
| // of the Apache-2.0 license. See the LICENSE file for details. | ||
|
|
||
| import ExtrinsicEra, { MortalEra } from './ExtrinsicEra'; | ||
| import U64 from '../primitive/U64'; | ||
|
|
||
| describe('ExtrinsicEra', () => { | ||
|
|
||
| it('decodes an Extrinsic Era with immortal', () => { | ||
| const extrinsicEra = new ExtrinsicEra(new Uint8Array([0])); | ||
| expect(extrinsicEra.asMortalEra).toBeUndefined(); | ||
| expect(extrinsicEra.asImmortalEra).toBeDefined(); | ||
| }); | ||
|
|
||
| it('decodes an Extrinsic Era from u8 as mortal', () => { | ||
| const extrinsicEra = new ExtrinsicEra(new Uint8Array([1, 78, 156])); | ||
| expect((extrinsicEra.asMortalEra as MortalEra).period.toNumber()).toEqual(32768); | ||
| expect((extrinsicEra.asMortalEra as MortalEra).phase.toNumber()).toEqual(20000); | ||
| }); | ||
|
|
||
|
|
||
| it('encode an Extrinsic Era from Object with blocknumber & period as mortal instance', () => { | ||
| const mortalIndex = 1; | ||
| const extrinsicEra = new ExtrinsicEra({ startBlockNumber: new U64(1400), endBlockNumber: new U64(1600) }, mortalIndex); | ||
| expect((extrinsicEra.asMortalEra as MortalEra).period.toNumber()).toBeGreaterThan(4); | ||
|
KarishmaBothara marked this conversation as resolved.
Outdated
|
||
| expect((extrinsicEra.asMortalEra as MortalEra).period.toNumber()).toEqual(256); | ||
| expect((extrinsicEra.asMortalEra as MortalEra).phase.toNumber()).toEqual(120); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,33 +2,156 @@ | |
| // This software may be modified and distributed under the terms | ||
| // of the Apache-2.0 license. See the LICENSE file for details. | ||
|
|
||
| import EnumType from '../codec/EnumType'; | ||
| import {isHex, isU8a, hexToU8a, isObject} from '@polkadot/util'; | ||
| import Tuple from '../codec/Tuple'; | ||
| import U64 from '../primitive/U64'; | ||
| import U8 from '../primitive/U8'; | ||
| import U16 from '../primitive/U16'; | ||
| import { AnyU8a } from '../types'; | ||
| import BlockNumber from "@polkadot/types/type/BlockNumber"; | ||
| import U8a from "@polkadot/types/codec/U8a"; | ||
|
|
||
| import { u8aToU8a } from '@polkadot/util'; | ||
| interface EraMethod { | ||
| startBlockNumber: BlockNumber; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. they can just be number. |
||
| endBlockNumber: BlockNumber; | ||
| } | ||
|
|
||
| export default class ExtrinsicEra extends EnumType<ImmortalEra | MortalEra> { | ||
| constructor (value?: any, index?: number) { | ||
| super({ ImmortalEra, MortalEra }, value, index); | ||
| } | ||
|
|
||
| /** | ||
| * @description Returns the item as a [[ImmortalEra]] | ||
| */ | ||
| get asImmortalEra (): ImmortalEra | undefined{ | ||
| if (this.index === 0) { | ||
| return this.value as ImmortalEra; | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| /** | ||
| * @description Returns the item as a [[MortalEra]] | ||
| */ | ||
| get asMortalEra (): MortalEra | undefined { | ||
|
KarishmaBothara marked this conversation as resolved.
Outdated
KarishmaBothara marked this conversation as resolved.
Outdated
|
||
| if (this.index === 1) { | ||
|
KarishmaBothara marked this conversation as resolved.
Outdated
|
||
| return this.value as MortalEra; | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| /** | ||
| * @description Encodes the value as a Uint8Array as per the parity-codec specifications | ||
| * @param isBare true when the value has none of the type-specific prefixes (internal) | ||
| */ | ||
| toU8a (isBare?: boolean): Uint8Array { | ||
| if (this.index === 0 ) { | ||
| return super.toU8a() | ||
| } else { | ||
| return (this.asMortalEra as MortalEra).toU8a(isBare); | ||
|
KarishmaBothara marked this conversation as resolved.
Outdated
|
||
| } | ||
| } | ||
| } | ||
|
|
||
| export class ImmortalEra extends U8a { | ||
| constructor(value?: AnyU8a) { | ||
| super(value); | ||
|
KarishmaBothara marked this conversation as resolved.
|
||
| } | ||
| } | ||
|
|
||
| import U8a from '../codec/U8a'; | ||
| export type MortalEraValue = [U8, U8]; | ||
|
|
||
| /** | ||
| * @name ExtrinsicEra | ||
| * @name MortalEra | ||
| * @description | ||
| * The era for an extrinsic, indicating either a mortal or immortal extrinsic | ||
| * The MortalEra for an extrinsic, indicating period and phase | ||
| */ | ||
| export default class ExtrinsicEra extends U8a { | ||
| constructor (value?: AnyU8a) { | ||
| super( | ||
| ExtrinsicEra.decodeExtrinsicEra(value) | ||
| ); | ||
| export class MortalEra extends Tuple { | ||
|
ianhe8x marked this conversation as resolved.
|
||
| constructor (value?: any) { | ||
| super({ | ||
| period : U8, phase : U8 | ||
| }, MortalEra.decodeMortalEra(value)); | ||
| } | ||
|
|
||
| private static decodeMortalEra (value: EraMethod | Uint8Array | string): MortalEraValue { | ||
|
KarishmaBothara marked this conversation as resolved.
Outdated
|
||
| if (isHex(value)) { | ||
| return MortalEra.decodeMortalEra(hexToU8a(value.toString())); | ||
| } else if (isU8a(value)) { | ||
| const u8a = value; | ||
| const first = u8a.subarray(0, 1); | ||
| let second = u8a.subarray(1, 2); | ||
| const encoded = new U64(new U64(first).toNumber() + (new U64(second).toNumber() << 8)); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can just use them as type number. (no point wrap them with U64 but toNumber() every time use them) |
||
| const period = new U64(2 << (encoded.toNumber() % (1 << 4))); | ||
| const factor = 12; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can just use 12 in next line |
||
| const quantizeFactor = Math.max(period.toNumber() >> factor, 1); | ||
| let phase = (encoded.toNumber() >> 4) * quantizeFactor; | ||
| if (period.toNumber() >= 4 && phase < period.toNumber()) { | ||
| return [new U8(period), new U8(phase)]; | ||
| } | ||
| throw new Error('Invalid data passed to Mortal era'); | ||
| } else if (isObject(value)) { | ||
| const current = value.startBlockNumber; | ||
| const period = value.endBlockNumber.toNumber() - value.startBlockNumber.toNumber(); | ||
| let calPeriod = Math.pow(2, Math.ceil(Math.log2(period))); | ||
| calPeriod = Math.min( Math.max(calPeriod, 4), 1<< 16); | ||
| const phase = current.toNumber() % calPeriod; | ||
| const factor = 12; | ||
| const quantizeFactor = calPeriod >> factor > 1 ? calPeriod >> factor : 1; | ||
| let quantizedPhase = phase / quantizeFactor * quantizeFactor; | ||
| return [new U8(calPeriod), new U8(quantizedPhase)]; | ||
| } | ||
| return [new U8(), new U8()]; | ||
| } | ||
| /** | ||
| * @description The justification [[U64]] | ||
| */ | ||
| get period (): U8 { | ||
| return this[0] as U8; | ||
| } | ||
|
|
||
| /** | ||
| * @description The round this justification wraps as a [[U64]] | ||
| */ | ||
| get phase (): U8 { | ||
| return this[1] as U8; | ||
| } | ||
|
|
||
| /** | ||
| * @description Encodes the value as a Uint8Array as per the parity-codec specifications | ||
| * @param isBare true when the value has none of the type-specific prefixes (internal) | ||
| */ | ||
| toU8a (isBare?: boolean): Uint8Array { | ||
|
|
||
| const period = new U64(this.period); | ||
|
KarishmaBothara marked this conversation as resolved.
Outdated
|
||
| const phase = new U64(this.phase); | ||
| const quantize_factor = Math.max(period.toNumber() >> 12, 1); | ||
| const trailingZeros = this.getTrailingZeros(period); | ||
| const encoded = Math.min(15, Math.max(1, trailingZeros - 1)) + (((phase.toNumber() / quantize_factor) << 4)); | ||
| const encode = new U16(encoded); | ||
|
KarishmaBothara marked this conversation as resolved.
Outdated
|
||
| const first = encode.toNumber() >> 8; | ||
| const second = encode.toNumber() & 0xff; | ||
| return new Uint8Array([second, first]); | ||
| } | ||
|
|
||
| static decodeExtrinsicEra (value?: AnyU8a): Uint8Array { | ||
| if (value) { | ||
| const u8a = u8aToU8a(value); | ||
| getTrailingZeros(period: U64) { | ||
| let zeros = ''; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| let periodN = period.toNumber(); | ||
| periodN = parseInt(Number(periodN).toString(2)); | ||
| //periodN = periodN.toString(2) | ||
|
|
||
| // If we have a zero byte, it is immortal (1 byte in length), otherwise we have | ||
| // the era details following as another byte | ||
| return u8a.subarray(0, (u8a[0] === 0) ? 1 : 2); | ||
| while (periodN % 10 == 0) { | ||
| periodN = periodN /= 10; | ||
| zeros += 0; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. zeros.push(0) |
||
| } | ||
| return zeros.length; | ||
| } | ||
|
|
||
|
|
||
| return new Uint8Array([0]); | ||
| birth(current: U64) { | ||
| const b = Math.floor((Math.max(current.toNumber(),this.phase.toNumber()) - this.phase.toNumber()) / this.period.toNumber()) * this.period.toNumber() + this.phase.toNumber(); | ||
| return new U64(b); | ||
| } | ||
|
|
||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.