From 0d68f98c75a08db04a8a187a9de87bd8fc8faa98 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 29 Jul 2019 21:23:34 +0200 Subject: [PATCH] Extra block author for babe (#1227) * Update examples for 0.90 * Fix number typo * Adapth to use timestamp.now (blockPeriod now in all versions) * Babe extract block author * TODO for cleaner aura extraction * Update Babe id * Update & split tests --- .../api-derive/src/type/HeaderExtended.ts | 18 +++++------- packages/types/src/interfaceRegistry.ts | 9 +++++- .../types/src/interfaces/babe/definitions.ts | 9 +++++- packages/types/src/interfaces/babe/types.ts | 18 +++++++++++- .../Generic/ConsensusEngineId.spec.ts | 18 ++++++++++++ .../primitive/Generic/ConsensusEngineId.ts | 29 ++++++++++++------- .../src/primitive/Generic/Digest.spec.ts | 12 -------- 7 files changed, 77 insertions(+), 36 deletions(-) create mode 100644 packages/types/src/primitive/Generic/ConsensusEngineId.spec.ts diff --git a/packages/api-derive/src/type/HeaderExtended.ts b/packages/api-derive/src/type/HeaderExtended.ts index ff1ad897a1..a9de5a7af7 100644 --- a/packages/api-derive/src/type/HeaderExtended.ts +++ b/packages/api-derive/src/type/HeaderExtended.ts @@ -5,7 +5,7 @@ import { AccountId, Header } from '@polkadot/types/interfaces'; import { AnyJsonObject, Constructor } from '@polkadot/types/types'; -import { u64, ClassOf } from '@polkadot/types'; +import { ClassOf } from '@polkadot/types'; // This is a bit hacky, but is exactly what it resolves to when compiled - // and as a bonus is gets the typing right @@ -26,15 +26,14 @@ export default class HeaderExtended extends _Header { return; } - let slot: u64 | undefined; const [pitem] = header.digest.logsWith('PreRuntime'); // extract from the substrate 2.0 PreRuntime digest if (pitem) { const [engine, data] = pitem.asPreRuntime; - if (engine.isAura) { - slot = engine.extractSlot(data); + if (engine.isBabe || engine.isAura) { + this._author = engine.extractAuthor(data, sessionValidators); } } else { const [citem] = header.digest.logsWith('Consensus'); @@ -44,22 +43,19 @@ export default class HeaderExtended extends _Header { const [engine, data] = citem.asConsensus; if (engine.isAura) { - slot = engine.extractSlot(data); + this._author = engine.extractAuthor(data, sessionValidators); } } else { const [sitem] = header.digest.logsWith('SealV0'); // extract author from the seal (pre substrate 1.0, backwards compat) if (sitem) { - slot = sitem.asSealV0[0]; + this._author = sessionValidators[ + sitem.asSealV0[0].modn(sessionValidators.length) + ]; } } } - - // found a slot? Great, extract the validator - if (slot) { - this._author = sessionValidators[slot.modn(sessionValidators.length)]; - } } /** diff --git a/packages/types/src/interfaceRegistry.ts b/packages/types/src/interfaceRegistry.ts index 79e03dbc78..efa5a4284a 100644 --- a/packages/types/src/interfaceRegistry.ts +++ b/packages/types/src/interfaceRegistry.ts @@ -8,7 +8,7 @@ import { Keys, SessionIndex } from './interfaces/session'; import { AuthorityWeight, NextAuthority, PendingPause, PendingResume, StoredPendingChange, StoredState } from './interfaces/grandpa'; import { ApprovalFlag, SetIndex, Vote, VoteIndex, VoteThreshold, VoterInfo } from './interfaces/elections'; import { InclusionHeight, Uncle, UncleEntryItem } from './interfaces/authorship'; -import { BabeWeight } from './interfaces/babe'; +import { BabeWeight, RawBabePreDigest, SlotNumber } from './interfaces/babe'; import { BalanceLock, VestingSchedule, WithdrawReasons } from './interfaces/balances'; import { MemberCount, ProposalIndex, Votes } from './interfaces/collective'; import { AliveContractInfo, CodeHash, ContractInfo, ContractStorageKey, Gas, PrefabWasmModule, PrefabWasmModuleReserved, Schedule, SeedOf, TombstoneContractInfo, TrieId } from './interfaces/contracts'; @@ -300,6 +300,13 @@ export interface InterfaceRegistry { 'Compact': Compact; 'Option': Option; 'Vec': Vec; + SlotNumber: SlotNumber; + 'Compact': Compact; + 'Option': Option; + 'Vec': Vec; + RawBabePreDigest: RawBabePreDigest; + 'Option': Option; + 'Vec': Vec; VestingSchedule: VestingSchedule; 'Option': Option; 'Vec': Vec; diff --git a/packages/types/src/interfaces/babe/definitions.ts b/packages/types/src/interfaces/babe/definitions.ts index 340c594f21..3d512010a2 100644 --- a/packages/types/src/interfaces/babe/definitions.ts +++ b/packages/types/src/interfaces/babe/definitions.ts @@ -4,6 +4,13 @@ export default { types: { - BabeWeight: 'u64' + BabeWeight: 'u64', + SlotNumber: 'u64', + RawBabePreDigest: { + slotNumber: 'SlotNumber', + authorityIndex: 'u64', // AuthorityIndex (also in aura, same size) + vrfOutput: 'H256', // should be '[u8; 32]' (generator support lacking here) + vrfProof: 'H256' // should be '[u8; 32]' + } } }; diff --git a/packages/types/src/interfaces/babe/types.ts b/packages/types/src/interfaces/babe/types.ts index 5b3dba2995..30ef31be6f 100644 --- a/packages/types/src/interfaces/babe/types.ts +++ b/packages/types/src/interfaces/babe/types.ts @@ -1,6 +1,22 @@ // Auto-generated via `yarn build:interfaces`, do not edit -import { u64 } from '../../primitive'; +import { Struct } from '../../codec'; +import { H256, u64 } from '../../primitive'; /** u64 */ export type BabeWeight = u64; + +/** Struct */ +export interface RawBabePreDigest extends Struct { + /** SlotNumber */ + readonly slotNumber: SlotNumber; + /** u64 */ + readonly authorityIndex: u64; + /** H256 */ + readonly vrfOutput: H256; + /** H256 */ + readonly vrfProof: H256; +} + +/** u64 */ +export type SlotNumber = u64; diff --git a/packages/types/src/primitive/Generic/ConsensusEngineId.spec.ts b/packages/types/src/primitive/Generic/ConsensusEngineId.spec.ts new file mode 100644 index 0000000000..ddbdca431b --- /dev/null +++ b/packages/types/src/primitive/Generic/ConsensusEngineId.spec.ts @@ -0,0 +1,18 @@ +// 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 '../../injector'; + +import ConsensusEngineId, { CID_AURA, CID_BABE, CID_GRPA } from './ConsensusEngineId'; + +describe('ConsensusEngineId', (): void => { + it('creates a valid id for aura', (): void => { + expect(ConsensusEngineId.stringToId('FRNK')).toEqual(CID_GRPA); + expect(ConsensusEngineId.stringToId('aura')).toEqual(CID_AURA); + }); + + it('reverses an id to string for babe', (): void => { + expect(ConsensusEngineId.idToString(CID_BABE)).toEqual('BABE'); + }); +}); diff --git a/packages/types/src/primitive/Generic/ConsensusEngineId.ts b/packages/types/src/primitive/Generic/ConsensusEngineId.ts index aace6cdf2c..a797b37572 100644 --- a/packages/types/src/primitive/Generic/ConsensusEngineId.ts +++ b/packages/types/src/primitive/Generic/ConsensusEngineId.ts @@ -2,15 +2,18 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import BN from 'bn.js'; -import { assert, bnToBn } from '@polkadot/util'; +import { AccountId } from '../../interfaces/runtime'; +import BN from 'bn.js'; +import { bnToBn } from '@polkadot/util'; + +import createType from '../../codec/createType'; import Bytes from '../Bytes'; import U32 from '../U32'; import U64 from '../U64'; const CID_AURA = 0x61727561; // 'aura' -const CID_BABE = 0x65626162; // 'babe' +const CID_BABE = 0x45424142; // 'BABE' const CID_GRPA = 0x4b4e5246; // 'FRNK' (don't ask, used to be afg1) export { CID_AURA, CID_BABE, CID_GRPA }; @@ -57,15 +60,21 @@ export default class ConsensusEngineId extends U32 { } /** - * @description From the input bytes, decode into an aura-tuple + * @description From the input bytes, decode into an author */ - public extractSlot (bytes: Bytes): U64 { - assert(this.isAura, 'Invalid engine for asAura conversion'); + public extractAuthor (bytes: Bytes, sessionValidators: AccountId[]): AccountId { + if (this.isAura) { + // TODO We really want proper decoding of the digest as below (i.e. via type) + return sessionValidators[ + new U64(bytes.toU8a(true).subarray(0, 8)).modn(sessionValidators.length) + ]; + } else if (this.isBabe) { + return sessionValidators[ + createType('RawBabePreDigest', bytes.toU8a(true)).authorityIndex.toNumber() + ]; + } - return new U64( - // no compact prefix, only use the correct number of supplied bytes - bytes.toU8a(true).subarray(0, 8) - ); + throw new Error('Invalid engine for extractAuthor conversion'); } /** diff --git a/packages/types/src/primitive/Generic/Digest.spec.ts b/packages/types/src/primitive/Generic/Digest.spec.ts index 263ab30975..74d5fb83db 100644 --- a/packages/types/src/primitive/Generic/Digest.spec.ts +++ b/packages/types/src/primitive/Generic/Digest.spec.ts @@ -6,7 +6,6 @@ import '../../injector'; import json3 from '../../json/Header.003.json'; import block1 from '../../json/SignedBlock.003.00.json'; -import ConsensusEngineId, { CID_AURA, CID_BABE, CID_GRPA } from './ConsensusEngineId'; import Digest from './Digest'; describe('Digest', (): void => { @@ -37,15 +36,4 @@ describe('Digest', (): void => { expect(logs.length).toEqual(1); expect(logs[0].type).toEqual('Seal'); }); - - describe('ConsensusId', (): void => { - it('creates a valid id for aura', (): void => { - expect(ConsensusEngineId.stringToId('FRNK')).toEqual(CID_GRPA); - expect(ConsensusEngineId.stringToId('aura')).toEqual(CID_AURA); - }); - - it('reverses an id to string for babe', (): void => { - expect(ConsensusEngineId.idToString(CID_BABE)).toEqual('babe'); - }); - }); });