Open darkfriend77 opened 4 years ago
That is correct, so far, there is no way to generate keys using this .NET library. We are using a modified version of subkey that will output the private key in 64-byte format. Here is how you can get the keys:
$ git clone github.com:usetech-llc/substrate.git
$ cd bin/utils/subkey
$ cargo build
$ cargo run -- generate
Finished dev [unoptimized + debuginfo] target(s) in 0.78s
Running `/home/greg/Development/src/polkadot/substrate_ut/target/debug/subkey generate`
Secret phrase `maple rather inject cage food unable enter economy adapt mandate novel start` is account:
Network ID/version: substrate
Secret seed: 0xce456c3f305bf2c31868b1f51eb297e8b304551f1e456758cfa555d0040b31f7
64-byte secret: 0x1B04EA5667F6D63B7D405503651F56129B64ED148336F35EECCA53716B872B0B542E9D846415B636BB1741C22C8BCA827CEF9D170B9E671E36B60345D18B3894
Public key (hex): 0xa805c199eaa3d4d3f0865691e94b3ce4a508ee68aef6d7b42642d0d5d389667d
Account ID: 0xa805c199eaa3d4d3f0865691e94b3ce4a508ee68aef6d7b42642d0d5d389667d
SS58 Address: 5Fs1cSCX2ZDvtfC6wvrWWFoQDRdcESLuoTyYofdE1AM7LVhD
I've stumbled on the issue that the Signer requires the 512-bit secret key, while most other libs and tools expose & use the 256-bit (aka MiniSecretKey) one. I've asked the question on Substrate Technical, and Jeff Burdges (from W3F) confirmed either can be used (the 512-bit secret key can be expanded from 256-bit one, see here).
Just for me to understand, what's the blocker for having an API equivalent to GenerateKeypairFromSeed ?
The Schnorrkel implementation is missing a few features to create keypairs.
something like that should be enough to create the keypairs. It's not much missing, here is my first try https://github.com/darkfriend77/SubstrateNetApi/commit/ef7e066dc99463f1f7d0d17ed0d538e803cc34a9
Why not use the sr25519-dotnet
lib ?
Hmm, I thought it will break the Unity3D compatibility, which is focused from our project, but I will give it a try to check this.
@darkfriend77 I just pushed some code over here : https://github.com/stiiifff/substrate-enterprise-sample-app/blob/de46e463335eb9fab22f32970e78da57bbeeb2f8/Parity.Substrate.EnterpriseSample/Services/AccountService.cs#L16
I can generate a mnemonic with the dotnetstandard-bip39
nuget, derive entropy & seed from the mnemonic, then create a keypair with the sr25519 dotnet lib
. I will push a PR to the sr25519 dotnet lib
to make it .net standard 2.1 compatible.
What you need to do manually for now is to build a native lib for https://github.com/Warchant/sr25519-crust. Just clone the repo, and build on your platform, then include the lib along the sr25519 dotnet lib
(I've tested it on Mac, x86_64 & arm64 android).
I will try to find the time to package & publish a proper Nuget for sr25519 dotnet lib
including the native libs for various platforms (/cc @gautamdhameja). That should be good enough for now.
I tested it in Unity3D and it seems to be fine, the only test that I need to do is that the signature can be verified by substrate to ... and of course we need more exposure, I added verify and sign byte[] message straight, currently only string is supported. mnemonic which match substrate would be super cool. Please use Standard 2.0 as 2.1 isn't supported in Unity3D so far. If 2.1 is need for Span and stuff like that I think ther eis a backported System.Memory package.
mnemonic
I will try to replace Schnorrkel by sr25519 dotnet lib and see if it will break tests.
@stiiifff It seems that the implementation sr25519 dotnet lib doesn't match the implementation which currently substrate is using that's probablly why there is an individual Schnorrkel implementaition, it's the version v0.11 corresponding to https://github.com/usetech-llc/polkadot_api_dotnet/blob/master/Schnorrkel/Sr25519v011.cs which it can verify.
We would need the version https://github.com/usetech-llc/polkadot_api_dotnet/blob/master/Schnorrkel/Sr25519v091.cs which is currently what can verify and sign messages with substrate.
@darkfriend77 I opened a PR https://github.com/gautamdhameja/sr25519-dotnet/pull/1. Please try with one of the native lib, I've built them from the latest master branch of the C bindings (https://github.com/Warchant/sr25519-crust) which is compatible with Schnorrkel v0.9.1.
Yes, the API's sr25519 is a bit behind. BTW, we are planning to bring it up to date in about the middle of October. Does that change things for you?
@stiiifff I used your branch PR (https://github.com/stiiifff/sr25519-dotnet/tree/netstd-2_1) branch and now it doesn't verify any of the signatures ... sr25519-crust seems to be on 0.85 ??
negative outcome
var simpleSign = Sr25519v011.SignSimple(pubKey, secKey, message);
Assert.True(Sr25519v011.Verify(simpleSign, pubKey, message));
Assert.True(sr25519_dotnet.lib.SR25519.Verify(message, simpleSign, pubKey)); <-- fails
negative outcome
var signedByAlic3 = Utils.HexToByteArray("0xa63c26a956af0218f800f0f0cf119f56139c824967b4e9f84ee3aa1d0c206a3eff7572a036568f89d8406df259c2bb93875725d284fb76187c8bb5fe0246cb8f");
Assert.True(Sr25519v091.Verify(signedByAlic3, publicKey, messag2));
Assert.True(sr25519_dotnet.lib.SR25519.Verify(messag2, signedByAlic3, publicKey)); <-- fails
@gregzaitsev We currently have no dependency as we have implemented ed25519 keypair generation to workaround this issue. I started a chat with you on riot, maybe we can elaborate the next steps together?
marked test fails ... but is fine with substrate
@stiiifff I used your branch PR (https://github.com/stiiifff/sr25519-dotnet/tree/netstd-2_1) branch and now it doesn't verify any of the signatures ... sr25519-crust seems to be on 0.85 ??
As mentioned in the PR, I built the libs from the current master which references v0.9.1 of Schnorrkel. Everything looks OK to me on that front.
@darkfriend77 OK, I found an issue in the sr25519-dotnet lib: https://github.com/gautamdhameja/sr25519-dotnet/blob/259d403cee7d08b7da764246c49bcbbf1e9af9c4/sr25519-dotnet.lib/SR25519.cs#L119. If you pass a string with chars that are not valid UTF8 characters, this is gonna mess the whole thing. This is obviously not the case when signing extrinsic ... I will fix it to accept an hexadecimal string and process it differently.
I wrote an hd wallet for polkadot, but I am not sure about my approach. This issue is also related to that and can you kindly check it out at #11
I was looking for way to derivate public keys from private keys.
Like the implementation .... in the sr25519 binding, GenerateKeypairFromSeed()
Is there something like that, I haven't found an functionality for derivation.