diff --git a/packages/api-derive/test/e2e/promise.spec.ts b/packages/api-derive/test/e2e/promise.spec.ts index 422e785db2..ecbbd8c3d6 100644 --- a/packages/api-derive/test/e2e/promise.spec.ts +++ b/packages/api-derive/test/e2e/promise.spec.ts @@ -6,8 +6,8 @@ import ApiPromise from '@plugnet/api/promise/Api'; import { BlockNumber } from '@plugnet/types'; import { WsProvider } from '@plugnet/rpc-provider'; -const WS_LOCAL = 'ws://127.0.0.1:9944/'; -// const WS_POC3 = 'wss://poc3-rpc.polkadot.io/'; +// const WS = 'ws://127.0.0.1:9944/'; +const WS = 'wss://poc3-rpc.polkadot.io/'; describe.skip('derive e2e', () => { let api: ApiPromise; @@ -17,7 +17,7 @@ describe.skip('derive e2e', () => { }); beforeEach(async (done) => { - api = await ApiPromise.create(new WsProvider(WS_LOCAL)); + api = await ApiPromise.create(new WsProvider(WS)); done(); }); @@ -29,4 +29,14 @@ describe.skip('derive e2e', () => { expect((block1 as BlockNumber).eq(block2)).toBe(false); }); + + it('subscribes to newHead, retrieving the actual validator', (done) => { + return api.derive.chain.subscribeNewHead(({ author }) => { + console.error('author', author.toString()); + + if (author) { + done(); + } + }); + }); }); diff --git a/packages/types/src/type/Digest.ts b/packages/types/src/type/Digest.ts index e03efbe93e..ae90191681 100644 --- a/packages/types/src/type/Digest.ts +++ b/packages/types/src/type/Digest.ts @@ -77,6 +77,39 @@ export class Consensus extends Tuple { Bytes }, value); } + + /** + * @description `true` if the engine matches aura + */ + get isAura (): boolean { + return this.engine.eq(0x61727561); // ['a', 'u', 'r', 'a'] + } + + /** + * @description The wrapped engine [[U32]] + */ + get engine (): U32 { + return this[0] as U32; + } + + /** + * @description The wrapped [[Bytes]] + */ + get data (): Bytes { + return this[1] as Bytes; + } + + /** + * @description The slot and signature extracted from the raw data (assuming Aura) + */ + get asAura (): [U64, Signature] { + const raw = this.data.toU8a(true); + + return [ + new U64(raw.subarray(0, 4)), + new Signature(raw.subarray(64)) + ]; + } } /** diff --git a/packages/types/src/type/Header.ts b/packages/types/src/type/Header.ts index 213c9f03f3..55cdc01752 100644 --- a/packages/types/src/type/Header.ts +++ b/packages/types/src/type/Header.ts @@ -8,6 +8,7 @@ import { blake2AsU8a } from '@plugnet/util-crypto'; import Compact from '../codec/Compact'; import Struct from '../codec/Struct'; +import U64 from '../primitive/U64'; import AccountId from './AccountId'; import BlockNumber from './BlockNumber'; @@ -101,11 +102,33 @@ export class HeaderExtended extends Header { constructor (header: Header | null = null, sessionValidators: Array = []) { super(header); - const digestItem = header && header.digest && header.digest.logs.find(({ type }) => type === 'Seal'); + if (!header || !header.digest || !sessionValidators.length) { + return; + } - this._author = digestItem && sessionValidators.length - ? sessionValidators[digestItem.asSeal.slot.toNumber() % sessionValidators.length] - : undefined; + let item = header.digest.logs.find((log) => log.isConsensus); + let slot: U64 | undefined; + + // extract author from the consensus (substrate 1.0, digest) + if (item) { + const consensus = item.asConsensus; + + if (consensus.isAura) { + slot = consensus.asAura[0]; + } + } else { + item = header.digest.logs.find((log) => log.isSeal); + + // extract author from the seal (pre substrate 1.0, backwards compat) + if (item) { + slot = item.asSeal.slot; + } + } + + // found a slot? Great, extract the validator + if (slot) { + this._author = sessionValidators[slot.toNumber() % sessionValidators.length]; + } } /**