I'm involved in a .NET substrate-based project and I started working towards an implementation for making balance transfers on Substrate.

I would swear that I'm doing everything exactly the same way that the @polkadot/* packages do, but in the end, when I submit my transaction, I get an error 1010 back, which means the signature verification failed, and I'm running out of ideas.

I have verified that:

  • The unsigned payload matches that of the polkadot packages.
  • The mnemonic is converted to the same public/secret pair.
  • That the signature can be verified by my code.
  • That the signature can be verified by @polkadot/* (!).
  • That the final payload matches one generated by @polkadot/*, minus the signature itself which is different every time, and the era, where I use an immortal era ([0]).

This is a gist containing all the values leading up to the final submission. At the time of writing, the sender's nonce is 44.

Eternally grateful to anyone who can shed some light.

  • For immortal, blockHash needs to be the same as genesisHash. (It will only differ for mortal, where the actual blockHash for the era begin is provided)
    – Jaco
    May 17, 2022 at 16:10
  • Did you try subkey verify to debug it? Otherwise make sure to use the correct signature prefix, for sr25519 its substrate. May 17, 2022 at 17:46
  • This is insane. I can't even validate a signature signed by polkadot in subkey. Updated the gist with code and output.
    – georgiosd
    May 18, 2022 at 8:48
  • 1
    After running more tests I found that even though the error points to the signature, the problem is not the signature but one of, or both of, the era and block hash. I tried going with era = 0 and block hash = genesis but I still get the same errors. Any ideas?
    – georgiosd
    May 18, 2022 at 14:39
  • 1
    See github.com/polkadot-js/wasm/issues/352 - your input is wrong into subkey. As per the first comment by me to your question above, your blockHash value is wrong and this will make the verification fail. (The linkes issue has the expected values as a comment as well)
    – Jaco
    May 18, 2022 at 15:28

1 Answer 1


After going down a rabbit hole with signatures and different implementations, I managed to get it working using the official schnorrkel crate.

I also had a bug where if I defined an immortal era, my code would use the runtime version of the genesis block, instead of the latest one.

  • Congrats :) - would you mind sharing more concretely how this was done for those looking here to see the an example of what worked? No huge pressure of course.
    – Nuke
    Jun 10, 2022 at 10:44
  • @DanShields gladly - what do you think would be helpful, specifically?
    – georgiosd
    Jun 12, 2022 at 10:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.