-
Notifications
You must be signed in to change notification settings - Fork 248
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
Simplify Extrinsic Creation and Signing #477
Comments
@jsdw many thanks for this example. It really helped me to better understand how extrinsics work and rewrite my code which initially was based on this guide. I got some errors using let from = AccountKeyring::Alice.to_account_id();
let alice_nonce = get_nonce(&from).await;
let runtime_version = get_runtime_version().await.unwrap();
let genesis_hash = get_genesis_hash().await;
let pallet_index: u8 = 8;
let method_index: u8 = 0;
let call_index: [u8; 2] = [pallet_index, method_index];
// extrinsic parameter
let address: Vec<u8> = "4d4c14c40d1b7ecb942455794693fa68".as_bytes().to_vec().encode();
// extrinsic parameter
let owner: [u8; 1] = [0];
let call: Vec<u8> = [call_index.to_vec(), address, owner.to_vec()].concat();
let extra = (
Era::Immortal,
Compact(alice_nonce),
Compact(0u128)
);
let additional = (
runtime_version.spec_version,
runtime_version.transaction_version,
genesis_hash,
genesis_hash,
);
let payload_to_be_signed: Vec<u8> = {
let mut encoded = call.clone();
extra.encode_to(&mut encoded);
additional.encode_to(&mut encoded);
encoded
};
let signature= {
if payload_to_be_signed.len() > 256 {
AccountKeyring::Alice.sign(&sp_core::blake2_256(&payload_to_be_signed)[..])
} else {
AccountKeyring::Alice.sign(&payload_to_be_signed)
}
};
let extrinsic = {
let mut encoded_inner = Vec::new();
(0b1000_0000 + 4u8).encode_to(&mut encoded_inner);
MultiAddress::Id::<_, u32>(from).encode_to(&mut encoded_inner);
MultiSignature::Sr25519(signature).encode_to(&mut encoded_inner);
extra.encode_to(&mut encoded_inner);
encoded_inner.extend(&call);
let len = Compact(encoded_inner.len() as u32);
let mut encoded = Vec::new();
len.encode_to(&mut encoded);
encoded.extend(&encoded_inner);
encoded
};
let extrinsic_hex = format!("0x{}", hex::encode(&extrinsic));
println!("RESULT HEX {:?}", extrinsic_hex); |
@amrbz My example code above was very quickly scrabbled together and was probably a little off; have a look at Line 283 in 6012d2a
Offhand what you've done looks good for a current Polkadot node though, so you may need to dig a little deeper. But, for a substrate node (ie |
@jsdw Thanks. May I ask on the error with use subxt::PairSigner;
let signer = PairSigner::new(AccountKeyring::Alice.pair()); But I got this error: ❯ cargo run rpc-substrate -> main ?
Compiling rpc-substrate v0.1.0 (/Users/amrbz/Dev/rust/rpc-substrate)
error[E0284]: type annotations needed for `PairSigner<T, E, sp_core::sr25519::Pair>`
--> src/main.rs:363:18
|
363 | let signer = PairSigner::new(AccountKeyring::Alice.pair());
| ------ ^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
| |
| consider giving `signer` the explicit type `PairSigner<T, E, _>`, where the type parameter `T` is specified
|
= note: cannot satisfy `<_ as Config>::Signature == _`
For more information about this error, try `rustc --explain E0284`.
error: could not compile `rpc-substrate` due to previous error So I can't try out |
In isolation, you'll need to tell it manually what typw let signer = PairSigner::<subxt::DefaultConfig, _, _>::new(AccountKeyring::Alice.pair()); |
Closed by #490 |
Some goals I have in mind here:
substrate
types.How:
client.create_signed
or perhapsextrinsic::create_signed
), so it's easy to see what's going on. Right now you have to dig through various traits and such to piece together how an extrinsic is encoded.create_signed
at the mo. Perhaps allow thenonce()
to be optionally pulled from these too (in the future, it might be that we can opt to pull other params from here to override the defaults).Signer
trait if useful/needed (we just want to be able to obtain the account ID and sign the relevant bytes, I think).SignedExtension
andUncheckedExtrinsic
; I don't think we need them if we handle encoding ourselves.I thought about codegen to create the extra/additional types, and it may help a little going forwards, but for now I couldn't see a compelling enough win by doing this (I like the current approach of passing useful details from the client like nonce etc in when constructing them, and not sure how to reconcile this with codegen). Instead, I want to make it as easy as possible to create and use custom extra/additional params for your chain.
These thoughts expressed in code:
As much as anything, the code above serves as a reference to myself or anybody else who'd like to implement this as a starting point to work from!
Anyway, Any thoughts and such would be appreciated! :)
Supercedes #390 and #187.
Closed by #490.
The text was updated successfully, but these errors were encountered: