1

I've come across how scripts are hashed in the electrum (stratum) protocol implementation by looking at the docs.

I'm using NBitcoin, and I've tried to generate this hash from a segwit address, first this way:

myPublicKey.WitHash.ScriptPubKey.Hash.ToString()

However, electrum servers throw an error saying that this hash is not valid. I'm guessing because this hash is of type HASH160 instead of SHA256 like the docs claim? (As I see that the hash generated by this technique is the same hash that appears below the address in a page like this.)

Also I'm wondering if I need to reverse the chain of characters myself or if NBitcoin's SHA256 methods would do it for me? All in all, how to get this hash with NBitcoin API so that Electrum servers are happy?

2 Answers 2

1

In F#:

let address = BitcoinAddress.Create("1HLoD9E4SDFFPDiYfNYnkBLQ85Y51J3Zb1", 
                                    NBitcoin.Network.Main)
let sha = NBitcoin.Crypto.Hashes.SHA256(address.ScriptPubKey.ToBytes())
let reversedSha = sha.Reverse().ToArray() // add `open System.Linq` at the top
NBitcoin.DataEncoders.Encoders.Hex.EncodeData reversedSha
-1

Electrum server expects scripts to be queried by their sha256 hash, regardless of script type. The name script hash is a bit confusing - it actually just means take the sha256 of the script. You should be using a bare sha256 method instead of the Hash one, which seems to hash the data for use with bitcoin transactions. I'm not sure which endianness is used by NBitcoin, but if you do end up needing to reverse it, you shouldn't reverse the individual characters, rather you should be reversing the raw bytes, or in case it's a string, then in groups of two characters.

6
  • I've tried both WitScriptId(account.PublicKey.WitHash.ScriptPubKey).ToString() (because WitScriptId constructor seems to call sha256) and also reversed via NBitcoin.DataEncoders.Encoders.Hex.EncodeData(WitScriptId(account.PublicKey.WitHash.ScriptPubKey).ToBytes().Reverse().ToArray()), but electrum servers return a balance of zero for these two options (but I know it's not zero)
    – knocte
    Jan 13, 2019 at 18:17
  • You shouldn't be using any bitcoin-specific hashes to hash the scriptpubkey. Try something like : github.com/MetacoSA/NBitcoin/blob/master/NBitcoin/Crypto/…
    – arubi
    Jan 13, 2019 at 18:31
  • now I've tried NBitcoin.DataEncoders.Encoders.Hex.EncodeData(NBitcoin.Crypto.Hashes.SHA256(account.PublicKey.ScriptPubKey.ToBytes())), and reversing it; and NBitcoin.DataEncoders.Encoders.Hex.EncodeData(NBitcoin.Crypto.Hashes.SHA256(account.PublicKey.WitHash.ScriptPubKey.ToBytes())) and reversing it, still zero balance
    – knocte
    Jan 13, 2019 at 18:52
  • Maybe post the contents of an example ccount.PublicKey.ScriptPubKey in your original question. Hard to know if you're hashing the correct blob.
    – arubi
    Jan 13, 2019 at 19:00
  • updated the question to reflect what you just asked
    – knocte
    Jan 14, 2019 at 4:02

Your Answer

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

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