Interacting With a Substrate Blockchain
How to use the slides - Full screen (new tab)
Interacting With a Substrate Blockchain
Interacting With a Substrate Blockchain
Notes:
Many of these interactions land in a wasm blob.
So what question you need to ask yourself there? which runtime blob.
almost all external communication happens over JSPN-RPC, so let's take a closer look.
JSON-RPC
JSON-RPC is a remote procedure call protocol encoded in JSON. It is similar to the XML-RPC protocol, defining only a few data types and commands.
---v
JSON-RPC
{
"jsonrpc": "2.0",
"method": "subtract",
"params": { "minuend": 42, "subtrahend": 23 },
"id": 3
}
{ "jsonrpc": "2.0", "result": 19, "id": 3 }
---v
JSON-RPC
- Entirely transport agnostic.
- Substrate based chains expose both
websocket
andhttp
(orwss
andhttps
, if desired).
with
--ws-port
and--rpc-port
, 9944 and 9934 respectively.
---v
JSON-RPC
-
JSON-RPC methods are conventionally written as
scope_method
- e.g.
rpc_methods
,state_call
- e.g.
-
author
: for submitting stuff to the chain. -
chain
: for retrieving information about the blockchain data. -
state
: for retrieving information about the state data. -
system
: information about the chain. -
rpc
: information about the RPC endpoints.
Notes:
Recall:
- https://paritytech.github.io/substrate/master/sc_rpc_api/index.html
- https://paritytech.github.io/substrate/master/sc_rpc/index.html
The full list can also be seen here: https://polkadot.js.org/docs/substrate/rpc/
---v
JSON-RPC
-
Let's look at a few examples:
-
system_name
,system_chain
,system_chainType
,system_health
,system_version
,system_nodeRoles
,rpc_methods
,state_getRuntimeVersion
,state_getMetadata
wscat \
-c wss://kusama-rpc.polkadot.io \
-x '{"jsonrpc":"2.0", "id": 42, "method":"rpc_methods" }' \
| jq
---v
JSON-RPC: Runtime Agnostic
- Needless to say, RPC methods are runtime agnostic. Nothing in the above tells you if FRAME is being used or not.
- Except... metadata, to some extent.
---v
JSON-RPC: Runtime API
- While agnostic, many RPC calls land in a runtime API.
- RPC Endpoints have an
at: Option<hash>
, runtime APIs do too, what a coincidence! 🌈- Recall the scope
state
?
- Recall the scope
---v
JSON-RPC: Extending
- The runtime can extend more custom RPC methods, but the new trend is to move toward using
state_call
.
---v
JSON-RPC: Safety
- Some PRC methods are unsafe 😱.
---v
JSON-RPC: Resilience
RPC-Server vs. Light Client
JSON-RPC: Application
-
On top of
SCALE
andJSON-RPC
, a large array of libraries have been built. -
PJS-API
/PJS-APPS
-
capi
-
subxt
-
Any many more!
Notes:
https://github.com/JFJun/go-substrate-rpc-client https://github.com/polkascan/py-substrate-interface more here: https://project-awesome.org/substrate-developer-hub/awesome-substrate
JSON-RPC: Mini Activity
In Kusama:
- Find the genesis hash..
- Number of extrinsics at block 10,000,000.
- The block number is stored under
twox128("System") ++ twox128("Number")
.- Find it now, and at block 10,000,000.
- Refer to the "Substrate; Show Me The Code" lecture to find the right RPC endpoints.
- You have 15 minutes!
Notes:
# 10,000,000 in hex
printf "%x\n" 10000000
# Genesis hash
wscat -c wss://kusama-rpc.polkadot.io -x '{"jsonrpc":"2.0", "id":72, "method":"chain_getBlockHash", "params": ["0x0"] }' | jq
# Hash of the block at height 10,000,000
wscat -c wss://kusama-rpc.polkadot.io -x '{"jsonrpc":"2.0", "id":72, "method":"chain_getBlockHash", "params": ["0x989680"] }' | jq
# The block at height 1,000,000
wscat -c wss://kusama-rpc.polkadot.io -x '{"jsonrpc":"2.0", "id":72, "method":"chain_getBlock", "params": ["0xdcbaa224ab080f2fbf3dfc85f3387ab21019355c392d79a143d7e50afba3c6e9"] }' | jq
# `0x26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac` now.
wscat -c wss://kusama-rpc.polkadot.io -x '{"jsonrpc":"2.0", "id":72, "method":"state_getStorage", "params": ["0x26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac"] }' | jq
# `0x26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac` at block 1,000,000.
wscat -c wss://kusama-rpc.polkadot.io -x '{"jsonrpc":"2.0", "id":72, "method":"state_getStorage", "params": ["0x26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac", "0xdcbaa224ab080f2fbf3dfc85f3387ab21019355c392d79a143d7e50afba3c6e9"] }' | jq
Notice that this number that we get back is the little endian (SCALE) encoded value that we passed in at first.
Polkadot JS API
A brief introduction.
Excellent tutorial at: https://polkadot.js.org/docs/
---v
Polkadot JS API
---v
PJS: Overview
api.registry
api.rpc
---v
PJS: Overview
Almost everything else basically builds on top of api.rpc
.
api.tx
api.query
api.consts
api.derive
Please revise this while you learn FRAME, and they will make perfect sense!
---v
PJS: Workshop 🧑💻
Notes:
import { ApiPromise, WsProvider } from "@polkadot/api";
const provider = new WsProvider("wss://rpc.polkadot.io");
const api = await ApiPromise.create({ provider });
api.stats;
api.isConnected;
// where does this come from?
api.runtimeVersion;
// where does this come from?
api.registry.chainDecimals;
api.registry.chainTokens;
api.registry.chainSS58;
// where does this come from?
api.registry.metadata;
api.registry.metadata.pallets.map(p => p.toHuman());
api.registry.createType();
api.rpc.chain.getBlock()
api.rpc.system.health()
await api.rpc.system.version()
await api.rpc.state.getRuntimeVersion()
await api.rpc.state.getPairs("0x")
await api.rpc.state.getKeysPaged("0x", 100)
await api.rpc.state.getStorage()
await api.rpc.state.getStorageSize("0x3A636F6465"),
https://polkadot.js.org/docs/substrate/rpc#getstoragekey-storagekey-at-blockhash-storagedata
A few random other things:
api.createType("Balance", new Uint8Array([1, 2, 3, 4]));
import { blake2AsHex, xxHashAsHex } from "@polkadot/util-crypto";
blake2AsHex("Foo");
xxHashAsHex("Foo");
subxt
- Something analogous to
PJS
for Rust. - The real magic is that it generates the types by fetching the metadata at compile time, or linking it statically.
- ..It might need manual updates when the code, and therefore the metadata changes.
Additional Resources! 😋
Check speaker notes (click "s" 😉)
Notes:
- see "Client Libraries" here: https://project-awesome.org/substrate-developer-hub/awesome-substrate
- https://paritytech.github.io/json-rpc-interface-spec/introduction.html
- Full
subxt
guide: https://docs.rs/subxt/latest/subxt/book/index.html