Solution:
I would get extrinsics of the finalized head by:
- chain_getFinalizedHead to get the hash of the best finalized block.
- Pass that block hash to chain_getBlock to get the signed block.
chain_getFinalizeHead uses the client's local information, so it is not coming from the runtime.
Context:
In the use case you describe, I do not think it makes sense to use the justification field to check if a block is finalized. Most blocks from a GRANDPA based chain will not have a justification for several reasons:
- The justification may not exist at all because GRANDPA finalizes a chain, not a block. (i.e you can always prove Canon block #5 is final with a justification for Canon block #10 and in practice finalization happens every few blocks, not every block.)
- The current implementation of GRANDPA only needs to store the justification
for the first block of a session on chain, which is when the GRANDPA authority set may change. Syncing clients need to verify the finality of every GRANDPA authority set change and they use the justification stored on chain to do so.
- Currently, periodic justifications are stored in chain state at a more frequent rate than session change.
It is worth noting that the client does store justification alongside each block in its local DB, but other than the cases mentioned above, they are not part of runtime state.
Credits to André Silva, as most of this response is information he explained to me.