Great guide and mostly it's easy to understand. But i don't understand the 8th steps, is it encode/decode result from Bech32 characters?
Yes. Note that step7 is the hexadecimal representation of an array of 5-bit integers {0, 14, 20, 15, 7, ..., 11, 21} so 0 is item at index 0 of B32Chars or the letter q and 14 is the character at index 14 or w, 20 is 5 and so on. In C♯ string B32Chars = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; StringBuilder result = new StringBuilder(); foreach (byte item in step7Array) { result.Append(B32Chars[item]); }
Basically this: .join in python implementation ( https://github.com/sipa/bech32/blob/master/ref/python/segwit_addr.py#L59) or the for loop in JavaScript implementation ( https://github.com/sipa/bech32/blob/master/ref/javascript/bech32.js#L74-L76)
|
|
|
Bitcoin wiki has a pretty good step-by-step explanation of how to go from a public key to a base58_encoded address which contains the values for each step of the way[1]. But unfortunately I could not find anything similar for Bech32_encoding. Additionally I found the reference implementations a bit confusing[2]! The information is out there[3] but I feel like having it step-by-step like "[1]" can make it a lot easier specially for developers. For example during unit testing I was getting a different address ( bc1qp63uahgrxged4z5jswyt5dn5v3lzsem6c0qqhg8) for below public key and I wasn't sure where the bug was coming from, this visualization helped me [4] realize I was appending the version byte before converting the bits instead of after. So hopefully these steps can help someone like me looking for them. How to create a Bech32 address from a public key: 1. Having a compressed[5] public key (0x02 or 0x03 followed by 32 byte X coordinate): 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 2. Perform SHA-256 hashing on the public key: 0f715baf5d4c2ed329785cef29e562f73488c8a2bb9dbc5700b361d54b9b0554 3. Perform RIPEMD-160 hashing on the result of SHA-256: 751e76e8199196d454941c45d1b3a323f1433bd6 4. The result of step 3 is an array of 8-bit unsigned integers (base 2^8=256) and Bech32 encoding converts this to an array of 5-bit unsigned integers (base 2^5=32) so we "squash" the bytes to get: in hex: 0e140f070d1a001912060b0d081504140311021d030c1d03040f1814060e1e16 in numbers: 14 20 15 07 13 26 00 25 18 06 11 13 08 21 04 20 03 17 02 29 03 12 29 03 04 15 24 20 06 14 30 22 5 bits binary: 01110 10100 01111 00111 01101 11010 00000 11001 10010 00110 01011 01101 01000 10101 00100 10100 00011 10001 00010 11101 00011 01100 11101 00011 00100 01111 11000 10100 00110 01110 11110 10110 5. Add the witness version byte in front of the step 4 result (current version is 0): 000e140f070d1a001912060b0d081504140311021d030c1d03040f1814060e1e16 6. Compute the checksum by using the data from step 5 and the H.R.P (bc for MainNet and tb for TestNet) 7. Append the checksum to result of step 5 (we now have an array of 5-bit integers): 000e140f070d1a001912060b0d081504140311021d030c1d03040f1814060e1e160c0709110b15 8. Map each value to its corresponding character in Bech32Chars ( qpzry9x8gf2tvdw0s3jn54khce6mua7l) 00 -> q, 0e -> w,... qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 9. A Bech32_encoded address consists of 3 parts: HRP + Separator + Data: bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 The final result from step 9 is the same as example in BIP173[6] References: [1] https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses[2] https://github.com/sipa/bech32[3] https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki[4] https://en.bitcoin.it/w/images/en/4/48/Address_map.jpg[5] Only compressed public keys are allowed: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#restrictions-on-public-key-type[6] https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#examples
|
|
|
No No No! You are horribly mistaken and completely wrong.
Oh, man. I though I've got the hang of Scripts in bitcoin. I have to go back and review things now. Thanks, I fixed the comment too.
|
|
|
I am not an expert but here is what I see, your program was broken and made a mistake. You have a private key which has the public key: 02835613e6e22843ce7dafc5d22a2763a8428b81f3d44dced0fd860f08be7a29df
The hash160 of your public key is: 2ee67d879ccf17daec87b4ed4a6cecdd9b3f64a0
Which means your ScriptPubKey is if you use P2WPKH (bc1q9mn8mp.... address): 00 14 2ee67d879ccf17daec87b4ed4a6cecdd9b3f64a0
Edit: This part was indeed wrong. So here is the fix, thanks to achow101 (below comment) The P2WPKH nested in P2SH is going to hash the ScriptPubKey of P2WPKH So RIPEMD160(SHA256(00142ee67d879ccf17daec87b4ed4a6cecdd9b3f64a0)) and the result is: 0976<...>2f38 and the scriptPubKey will be: a9 14 09763cb05dcea0f98f53b0f08651f92c5d2d2f38 87
If you treat 0976... as a hash160 then you get the following address: 1s2iywx94HudryMHsU2g1K9x8DB1cahGc
Which is why blockchain.info shows it, and probably why your program sent the funds there.
|
|
|
The last 7 characters of a private key are a checksum.
Apart from the fact that that particular key was missing 7 characters do you have any other reason for saying this? The reason I am asking this is because I can't think of any reason why checksum would be 7 characters! Maybe I am missing some mathematical facts but AFAIK checksum is 4 bytes and 4 bytes encoded with base58encoding will give you between 4 chars to 6 chars. 4 chars being {0, 0, 0, 0} which is equal to 1111 and 6 chars being {255, 255, 255, 255} which is equal to 7YXq9G. I also ran some random tests for fun and I didn't get a single 7 char! Random rnd = new Random(); byte[] bytes = new byte[4];
for (int i = 0; i < 100000000; i++) { rnd.NextBytes(bytes);
var b58enc = BtcB58Encoder.Encode(bytes, true); if (b58enc.Length == 7) { string result = b58enc; } }
Also do you have any idea how such keys missing last characters are technically being recovered, apart from the obvious "import it in bc.i"?
|
|
|
I like this analogy:
Imagine a massive wall of lockers. Each locker is 1mm by 1mm, and the entire wall of lockers is a square 2 light years on each side. When you choose a private key, you pick one of these lockers at random. When someone sends you bitcoins, there's some magical inbox which puts the bitcoins into your locker without telling the sender anything about the location of your locker.
The lockers don't have locks. If someone knew the location of your locker (ie. your private key), then they could just go take what's in it. Similarly, it's possible to choose a locker at random and find that someone has used it already at some point in the past. But there are just so many lockers that in reality it's never going to happen, even if humanity devotes all of its efforts to searching through all of the lockers.
But it is misleading, don't you think? It is creating the false image that you are "receiving" coins in your key where in fact nothing is being delivered to you, but instead is stored on another place (the blockchain) and has a little link inside of it saying it belongs to your key. I think a better analogy would be to call it a wall of keys like in a parking lot and the parking lot. There is the same wall but it contains keys on it. then there is the parking lot (the blockchain) that contains cars (the transaction outputs). When someone sends you a car ("bitcoin"), they don't send it to "the wall" instead they send it to the "parking lot" and only change the key that opens the door of that car. If someone knows where the key for a particular car in the parking lot is, they can go to that wall, take the key, open the car door and drive away.
|
|
|
Yes. The TXID is the nversion, txin, txout, and nlocktime fields. The wtxid is everything. Just concatenate everything together from the part where each field is broken down. The lengths are still there so you can just stick them all together.
I think you misunderstood my question! I already know how they is calculated. I am making a library and I just want data (the two hashes) to feed my Unit Tests. For example the TxID of the first transaction in [1] above is: e8151a2af31c368a35053ddd4bdb285a8595c769a3ad83e0fa02314a602d4609
I ended up using Electrum to get the transaction IDs. But I still don't have WTxIDs and I don't know how to get them. For instance is there any command in Bitcoin Core that I can use to get it?
|
|
|
Most of your links need fixing, they go to first page of BitcoinTalk.org
|
|
|
I don't think this is the appropriate board for this question, but then there is no Altcoin Technical Discussion board!
This is an interesting question that I was also wondering about recently so I did some research. Disappointingly the findings were somewhat contradictory. Some say it is possible and some say it isn't. The discussions about it being impossible are more reasonable. For instance ETH is not a currency so you shouldn't expect currency functions from it such as "payment". Ether which is the token you are sending is meant to be used as a fuel for smart contracts so technically you should have only 1 recipient. But I have seen people saying it is possible and saw one script for it (which I can't find now). But the problem was that the script was basically a loop making multiple transactions like a chain making multiple payments instead of paying all in one tx, at least that is what I figured.
If someone has any more information I would love to hear it...
|
|
|
Why not use Test Net? - It is already there. - It is bitcoin (just with a different blockchain) - It can be used with bitcoin Core software - It has no value and it will stay like it - It is mineable the same was as bitcoin but with lower difficulty - It doesn't require that much storage space - ... if it did you can start a new Test Net from genesis block.
|
|
|
3> the tag for address is notepad.pw I'm pretty sure that tag wasn't there yesterday, right? mainly every address on that transactions is tagged, also blockchain moved there domain so i think thats why most of the users missed it ! If the way to solve the puzzle was to know the address then why wasn't the address included initially?
|
|
|
It is customary to also include the address containing the said coins.
|
|
|
♯♯♯ or other coin's address.
You can not prevent that, because the only thing you can check is whether the address is valid or not. And if the address follows the same structure (eg. LTC's old multi sig, or BCH's addresses) it will be valid. You can ask the user to confirm he wants to send for example bitcoin to the address he just gave you but that won't prevent much.
|
|
|
"Unable to decode output address" Why?
Because Blockchain.info is a lazy company that never thought to write a couple of more lines of code to decode OP_Return outputs. You can always use other block explorers out there: https://www.smartbit.com.au/tx/1e946ab6ebe67cba4cfe5a7e737604a3e249bf1956e21dc7862aa1094614d22137,418.47242639 BTC is the total amount that was transferred within this block which is the sum of outputs in 2779 transactions. You can click on each transaction to see how much each of them are transferring and where their funds come from.
|
|
|
Thanks for the advises. I was trying to construct a wallet based on the private key. If it was incorrect, it threw exception. The initial code was done because somebody was asking if this is possible, he was missing only 2 characters. For such quick result this was good enough. Now I see how bad actually is I'll surely optimize it one of the days. And I have to use all the CPUs too. Unfortunately I have an Intel GPU so I have to stop at CPU (also I am not good enough to go for GPU programming, not yet). No worries. It is good to see a fellow C♯ Enthusiast. I will probably share the code for this one of these days. I am currently super busy and in my free time I am working on my BitcoinTransactionTool. There are a lot of things to learn and fix in that. But will probably clean up this project right afterwards and post in on GitHub. It is a small (<200 lines) project.
|
|
|
|