Skip to content
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

feat: add grandpa justifications mock rpc #695

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/core/src/blockchain/head-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class HeadState {
delete this.#storageListeners[id]
}

async subscrubeRuntimeVersion(cb: (block: Block) => void) {
async subscribeRuntimeVersion(cb: (block: Block) => void) {
const id = randomId()
const codeKey = stringToHex(':code')
this.#storageListeners[id] = [[codeKey], cb]
Expand Down
25 changes: 25 additions & 0 deletions packages/core/src/rpc/substrate/grandpa.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Handler } from '../shared.js'

export const grandpa_subscribeJustifications: Handler<void, string> = async (context, _params, { subscribe }) => {
let update = () => {}

const id = context.chain.headState.subscribeHead(() => update())
const callback = subscribe('grandpa_justifications', id, () => context.chain.headState.unsubscribeHead(id))

update = async () => {
const mockProof = '0x' + '7'.repeat(64)
callback(mockProof)
}

setTimeout(update, 50)

return id
}

export const grandpa_unsubscribeJustifications: Handler<[string], void> = async (
_context,
[subid],
{ unsubscribe },
) => {
unsubscribe(subid)
}
3 changes: 3 additions & 0 deletions packages/core/src/rpc/substrate/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import * as AuthorRPC from './author.js'
import * as ChainRPC from './chain.js'
import * as GrandpaRPC from './grandpa.js'
import * as PaymentRPC from './payment.js'
import * as StateRPC from './state.js'
import * as SystemRPC from './system.js'

export { AuthorRPC }
export { ChainRPC }
export { GrandpaRPC }
export { PaymentRPC }
export { StateRPC }
export { SystemRPC }

const handlers = {
...AuthorRPC,
...ChainRPC,
...GrandpaRPC,
...PaymentRPC,
...StateRPC,
...SystemRPC,
Expand Down
20 changes: 19 additions & 1 deletion packages/core/src/rpc/substrate/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,24 @@ export const state_getKeysPaged: Handler<[string, number, string, HexString], st
return block?.getKeysPaged({ prefix, pageSize, startKey })
}

/**
* Mock get proof of the runtime storage value.
*
* @param context
* @param params - [`keys`, `blockhash`]
*
* @return mock proof
*/
export const state_getReadProof: Handler<
[HexString[], HexString],
{ at: HexString; proof: HexString[] } | null
> = async (_context, [keys, hash]) => {
return {
at: hash,
proof: keys.map(() => ('0x' + '7'.repeat(64)) as HexString),
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way we could get a real proof here ? As far as I know, for this we don't need signing keys.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@serban300 I've implemented state_getReadProof to return proof of requested keys but the trie_state_root won't be the same as block trie_state_root. I don't know if correct hash is required and not sure if we can do that. Can you give this a try first before I look deeper into the implementation?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ermalkaleci thanks ! Yes, will try this. Just have to prioritize some reviews first, and then I will get to this. Hopefully this week.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked. This doesn't work. I'm getting an error when validating the storage proof. We would need the trie_state_root to be the same as the block trie_state_root. Since I think that's how we're validating the proof. Would that be possible ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure

}

/**
* @param context
* @param params - [`keys`, `blockhash`]
Expand Down Expand Up @@ -110,7 +128,7 @@ export const state_call: Handler<[HexString, HexString, HexString], HexString> =
*/
export const state_subscribeRuntimeVersion: Handler<[], string> = async (context, _params, { subscribe }) => {
let update = (_block: Block) => {}
const id = await context.chain.headState.subscrubeRuntimeVersion((block) => update(block))
const id = await context.chain.headState.subscribeRuntimeVersion((block) => update(block))
const callback = subscribe('state_runtimeVersion', id)
update = async (block) => callback(await block.runtimeVersion)
setTimeout(() => {
Expand Down
11 changes: 11 additions & 0 deletions packages/e2e/src/__snapshots__/grandpa.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`grandpa rpc > subscribeJustifications 1`] = `
[
[
"0x7777777777777777777777777777777777777777777777777777777777777777",
],
]
`;

exports[`grandpa rpc > subscribeJustifications 2`] = `"0x7ba5ba52f5b88fa5bcab5c1a0f7e158d845d93e1c70e9a5b42a7c3a9af681ee7"`;
10 changes: 10 additions & 0 deletions packages/e2e/src/__snapshots__/state.test.ts.snap

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions packages/e2e/src/grandpa.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { describe, expect, it } from 'vitest'

import { api, delay, dev, mockCallback, setupApi } from './helper.js'

setupApi({
endpoint: ['wss://rpc.ibp.network/polkadot'],
blockHash: '0xb012d04c56b65cfa1f47cb1f884d920f95d0097b1ed42f5da18d5e2a436c2f3e',
})

describe('grandpa rpc', () => {
it('subscribeJustifications', async () => {
const { callback, next } = mockCallback()
const unsub = await api.rpc.grandpa.subscribeJustifications(callback)

await next()
expect(callback.mock.calls).toMatchSnapshot()

callback.mockClear()

expect(await dev.newBlock()).toMatchSnapshot()

await next()

expect(callback.mock.calls).toMatchSnapshot()

callback.mockClear()

unsub()

expect(await dev.newBlock()).toMatchSnapshot()

await delay(100)

expect(callback).not.toHaveBeenCalled()
})
})
1 change: 1 addition & 0 deletions packages/e2e/src/state.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ describe('state rpc', () => {
await checkHex(api.rpc.state.getMetadata(env.acala.blockHash)).toMatchSnapshot()
const genesisHash = await api.rpc.chain.getBlockHash(0)
expect(await api.rpc.state.getMetadata(genesisHash)).to.not.be.eq(await api.rpc.state.getMetadata())
expect(await api.rpc.state.getReadProof(['0x123', '0x123'], env.acala.blockHash)).toMatchSnapshot()
})

it.todo('subscribeRuntimeVersion')
Expand Down
Loading