Bitcoin Forum
March 05, 2021, 11:36:56 AM *
News: Latest Bitcoin Core release: 0.21.0 [Torrent]
 
  Home Help Search Login Register More  
  Show Posts
Pages: [1] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 ... 144 »
1  Economy / Gambling / Re: "The Maharaja of Bitcointalk" Sports Bettors/Tipster Competition 🏆Free entry🏆 on: March 04, 2021, 04:44:34 PM
Looks like a great contest to me. I have registered for the same. Smiley

Will be using BTC as my preferred coin. Looking forward to see who's the sponsor. Wink
2  Other / Beginners & Help / Re: Addresses and keys on: March 01, 2021, 06:16:06 PM
Another thing I was thinking was what if you wrote down your private key on paper and that was how you saved it?

It would be a bad idea. The length of the private key is 51-52 characters long and since it's in Base58 format, it contains both lowercase and uppercase characters. A single mistake in writing down private key will result in an invalid key and it will become very difficult to recover it.

Best way to backup the private key is by first encrypting it and then keeping it either on external devices like USB key, CD, or other storage devices or generating the QR of the encrypted key and print it on a paper.
3  Local / India / Re: MoS, Mr. Anurag Thakur, spoke about CryptoCurrency in Rajya Sabha today! on: February 27, 2021, 09:00:18 AM
Some news are doing round that Government may not present crypto ban bill during current parliament session. They will postpone it till mansoon season.
I think this is good if true as this will give crypto community some more time to convince Government to regulate crypto instead of banning it.

Indeed. The chances of bill being presented in the current session is minimal. From the words of the minister, it seems like bill is still far from finished and government still haven't finalized their stand on the matter.

USDT price is currently trading @ Rs. 77-78 which shows that positivity has once again kicked in Indian Market. It is once again at the premium of 5-8% similar to what it was before the ban news came out.
4  Economy / Gambling discussion / Re: Sportsbet.io's English Premier League Football Pool Discussion Thread on: February 18, 2021, 04:22:34 PM
Congrats to webtricks for winning the yellow cap,he beat me to that in the last game yesterday of Everton.I had 0-2 and he 1-3 so he got just 1 point ahead of me.Still I am very happy with my performance this week being the person who climbed the most positions,11 positions to come from 29 to 18th place.Looking forward to the weekend games already.

Thanks! It was a close one between us, just 1 more correct prediction which resulted in first spot for me. And congrats for ranking up to Top 20. I am still hovering in 30-40 range. Cheesy


webtricks's second cap now. Shame it couldn't have gone to swogerino who hasn't won one yet and missed out by a point.

Damn! I become the first one to win two Yellow Caps this season and still not in Top 30! Just shows how inconsistent I have been!


This round was 12 match one so make sure to note that on the table as 19 points equals mole's record round (in a standard 10 match round).

I haven't been following the thread actively, can you tell me what consensus we have reached for deciding the winner for the max points in a round? Are we going to adjust rounds with more matches to 10? For example, will my score be considered as 19/1.2 = 15.83? 


I got both scores right yesterday. Shame I didn't do so well earlier in the round as I could've got the yellow cap.

Even I got both scores exactly right yesterday, Tongue
5  Other / Beginners & Help / Re: [Full Guide+Code]Seed Phrase & The Process of Deriving Bitcoin Addresses from It on: February 18, 2021, 04:03:25 PM
~~
Not quite correct. Entropy is not "the sequence of randomness" but the measure of randomness of discussed sequence  which is defined as a number (in log scale) of "guesses" needed to obtain relevant  sequence of "0" and "1".
~~

Right! Using the phrase 'measure of randomness' or simply 'randomness' would have been much better and accurate than 'sequence of randomness'. Corrected!



~~
BIP-84 is just defining a BIP-32 specific derivation path for P2WPKH addresses, similar to BIP-44 and BIP-49. The part you've implemented in that link is mainly the Bech32 encoding itself which is defined by BIP-173.

Indeed! Wrote 'bip-84' by mistake. Corrected!



In the above step the value for Last 256 bits is different from the HMAC hash generated in the previous step.

Your HMAC output in Level 1 is
HMAC(message, key) = e9356507b5d275f724123f4053c602fee00c99c4874b63d1714c04ecc196b86cd895767e700af9e 8a8dab225a785d3299431b85298ca94a2628c542b26d96231

but the value for Left 256 bits = 7fc9ce32a6aeffbeaf5057f266f0d6ed6383ed84f21c96d53c0c1e3838a87e24

So either of the one output is incorrect here.


Good catch! I mistakenly pasted wrong hash in Level 1. The correct hash is:

Code:
7fc9ce32a6aeffbeaf5057f266f0d6ed6383ed84f21c96d53c0c1e3838a87e2481d4b120fcd3a11837e5d035fc508bb8b31c47285fdd7506d8d264144b4d8df7

However, it's just a copy/paste error. The rest of the derivation is correct.



It seems you made the small typo. Should be "Process is same for the Master Public Key as well" instead of "Process is same for the Master Private Key as well."  Sure this a small misspell but it can mislead non-experienced user.

Corrected!



Thanks for the corrections guys and making the thread more accurate! Smiley
6  Economy / Gambling discussion / Re: UEFA Champions League Discussion Thread on: February 16, 2021, 03:31:04 PM
Barcelona is in disarray so I'm tipping on PSG to go through. But since Barcelona's playing at home, I kinda feel they will not lose today. PSG will be looking for that away goal though so I think BTTS is a good option here.

I beg to differ. Barcelona looks much more promising right now when compared to PSG. Barca surely have edge over PSG in forward and midfield departments. Defense is where Barca failed to convince so far. However, Pique was solid in the few matches he played at the start of the season, he is back and most probably will start on the right side of CB pairing today. If Araujo isn't injured then him and Pique would have been perfect pair. But since he isn't playing, I think PSG would be able to sink in one goal, however, Barca will dominate the match and most probably win both legs. Neymar and Di Maria will be big miss for PSG.

@Trofo suggested me to go for BTTS bet on every match tonight, it's weird but bold suggestion so will give it a try as parlay.  Cheesy
7  Economy / Gambling discussion / Re: DiceGames:doYouReally own all your chances? Introspection on common DG mechanism on: February 16, 2021, 02:45:31 PM
Quote
The probability of 3.00x payout will remain same

That's when taking a fix range, (like when you're playing with auto-bet),  but what of when the player's decision is coming to interact on the game,
I think of for example when the result will be from the (omitted) range,, "(as like in provably fair systems the result is been occurred but is just hidden)", there, whatever what will the player choice the result is sealed to be "false/to loss".
I think giving the player possibility to choose is itself a factor of hazard that influing 'the game'. So do this (randomity) from player acting do not influence on the randomness on the whole (system): [(randomness on draw)+(randomness on player choice/or interaction)] ??


Okay, now I got your point and it is a good one. This is where using the provably fair system in correct way becomes very important. I have seen some casinos which claim to be Provably Fair but change server seed after the player sets new client seed. This system gives undue advantage to the casino to determine the roll result even before player rolls the dice. In last one year or so, I have actively tried to persuade casinos to shift from this system and on my recommendation 5-6 casinos (such as FortuneJack, OneHash, SimpleDice) shifted to more impartial system.

In the current standard system of provably fairness (which is being used by all notable casinos), the player has complete autonomy to pick the client seed before placing the bet. If the player picks a new client seed before making the bet, it will entirely change the roll result leaving no advantage to casino (because casino has already committed the server seed). For example, let assume the casino is trying to cheat player and sets - 'XXAASSXX' as the server seed which when salted with the current client seed of the player generates the roll result of 52.17. But then before placing the bet, user changes his client seed thus changing the roll result and making the result out of the complete-control of both player and casino. If casino is following this system of provably fairness then selecting custom range or not will have zero impact on the probability.

And this also brings me to another important point which I keep on advocating on forum regularly is that the players should actively change their client seed before every betting session and verify some of their bets frequently using the third-party verifier too.
8  Economy / Gambling discussion / Re: DiceGames:doYouReally own all your chances? Introspection on common DG mechanism on: February 15, 2021, 04:49:07 PM
o_e_l_e_o is right! Restriction in choosing the range doesn't effect the probability. The probability of 3.00x payout will remain same no matter if you keep the range constant or change it constantly, provided casino is using strong RNG for generating server seed. The reason for this is that each bet is exclusive. The computation of each bet uses unique inputs which when used with strong hashing algorithm produces entirely different result from the precedent bet.

Anyhow, I created and ran a script to demonstrate the result using strong RNG for roll generation. I ran 5 sets of trial for each case containing 1,000,000 bets each. Here are the results:

CASE 1: Keeping the range constant - Roll under 33.00 i.e. [0.00-32.99] range

            WINS     LOSES
Set 1 - 329894   670106
Set 2 - 329977   670023
Set 3 - 329924   670076
Set 4 - 330425   669575
Set 5 - 329935   670065
Avg. - 330031  669969

CASE 2: Roll in range [0.00-32.99] for first 333,333 bets, roll in range [33.00-65.98] for next 333,333 bets and roll in range [67.01-99.99] for final 333,334 bets

            WINS     LOSES
Set 1 - 329628   670372
Set 2 - 329592   670408
Set 3 - 330024   669976
Set 4 - 330002   669998
Set 5 - 330385   669615
Avg. - 329926.2   670073.8

No significant variance found!
9  Other / Beginners & Help / Re: [Full Guide+Code]Seed Phrase & The Process of Deriving Bitcoin Addresses from It on: February 13, 2021, 07:03:11 PM
UPDATE: I have added the code for Bech32 addresses as well. The code for deriving Bech32 Address (using P2WPKH serialization format as defined in BIP-173) from public key has been added in bech32.js file which has been added in the #1 reply of the thread.

GitHub Link: https://github.com/web-tricks/seed-guide/blob/main/bech32.js

The code now supports the derivation of first 10 Bech32 Addresses which can be tested here: https://webtricks.website/seed/

You added the first 10 P2SH and P2PKH address formats. Why didn't you add the first 10 Bech32 (bc1) as well?



I will add the code to generate first 5 change addresses for all three formats in next update. Smiley
10  Economy / Exchanges / Re: FTX BTC options ??? on: February 13, 2021, 02:51:13 PM
I've only partly found it though, I can't see in options tables with strike prices etc, does anyone know where they are?

Are you talking about the order book? Well, you won't find it like that on FTX. FTX Options don't work on orderbook model, instead they work on 'Request for Quote' (RFQ) model. So, you will see something like the following image on Options page:



You can click 'Request Quote' and place your order. You can manually customize your order - Put/Call, Strike Price, Expiry Date, Limit Price and Buy/Sell. Then, your request will go under 'My Request' section and within few seconds, you will start seeing quotes from the other users under 'Best Quote (per contract)' column. It's up to you if you want to accept those quotes or let them go.

For example, If I place request for the Buy Call Option of 1 BTC at the strike price of $48K for tomorrow midnight, I will start receiving quotes after few seconds under 'My Request' section. Suppose, I get the quote of $400. I can accept that and have to pay $400 for the option upfront. Then, if bitcoin goes above $48,400 at the midnight tomorrow, I will end up in profit otherwise I will bear the loss (could be between $1-400).

Alternatively, you can make quotes for the requests others have placed under 'All Requests' section if you see any. But note- you will play opposite party as to 'Option Type', consider that while making quote.
11  Other / Beginners & Help / Re: [Full Guide+Code]Seed Phrase & The Process of Deriving Bitcoin Addresses from It on: February 10, 2021, 12:07:32 PM
~snip~
It really doesn't do that.
PBKDF2 is already a very weak key derivation function by design and using a very low iteration count (2048 instead of 10 million) isn't going to slow anything down either. In fact under the hood you are just computing about 4k HMACSHA512, suffice it to say that your CPU can compute millions of SHA512 in a second.

What people refer to as "increases security" is the passphrase that is used in BIP39 which I always argue that it cannot be considered a true security measure again due to weakness of the used KDF and the fact that there is no minimum size set for the passphrase and users aren't known for using strong passwords.

You are right. I may have over-glorified the use of PBKDF2 in the process. But the standard was proposed by the people behind Trezor wallet and they wanted to use this as the mechanism against brute-force. But due to the limitation of memory and computation constraint in Trezor device, they restricted to using 2048 rounds of PBKDF2 instead of using more iteration or using stronger KDF like Scrypt. However, like you said, it doesn't add anything on regular computer which is capable of computing 2048 rounds in a fraction of millisecond.

Passphrase on the contrary is a powerful security measure. But like you pointed out, due to no defined standard for picking the passphrase, users are tend to pick weaker and predictable passphrase. No wonder why most of the wallets don't force users to pick passphrase by default, some even don't have the option of adding passphrase. In my opinion, it's a smart move because:
  • If passphrase is strong and random and saved together with seed, it doesn't serve any purpose
  • If passphrase is strong and random and saved apart from seed, it increases the chance of misplacing the backup.
  • If passphrase is strong and random and only memorized, it increases the chance of forgetting the passphrase.
  • If passphrase is weak and predictable, it can easily be brute-forced

So, securely creating backup of seed is sufficient enough imo, no need to use passphrase at all.

PS: Changes have been made in the OP in Step 4. Thank you.
12  Other / Beginners & Help / Re: [Full Guide+Code]Seed Phrase & The Process of Deriving Bitcoin Addresses from It on: February 09, 2021, 09:14:30 PM
I have just one question/suggestion:

You added the first 10 P2SH and P2PKH address formats. Why didn't you add the first 10 Bech32 (bc1) as well?

I would also suggest that you add change addresses, at least the first 5 ones as well. If someone uses your code to recover lost coins, change addresses are very important as well.

Well, I initially thought of adding all possible P2SH, P2PKH and Bech32 addresses, both for main network and test network along with the change addresses. Even, wrote code accordingly. But when I was preparing the final version of code and thread, it was becoming extensively lengthy. Restricting it to 10 addresses for 2 formats have reduced the code lines in 'address.js' file by 70%.

But like you said, it would be great addition so I will add 10 Bech32 addresses and 5-5 change addresses for all three formats tomorrow. We can leave the explanation part and test network part for now.
13  Other / Beginners & Help / Re: [Full Guide+Code]Seed Phrase & The Process of Deriving Bitcoin Addresses from It on: February 09, 2021, 08:58:01 PM
NOTE: I have not included the guide on Extended Keys in this topic. Extended Keys are integral part of HD wallets and help in importing addresses hierarchically without the need of mnemonic code. But the topic is already lengthy enough so will do separate thread on Extended Keys in future.

9. JAVASCRIPT CODE


Notes:
  • I have tried to explain the code using comments but if your find difficulty in any piece of code, you are free to ask in this thread.
  • I have written code in one go without re-checking or testing so please don't use it in any kind of production.
  • Due to point 2. above, I may have made mistakes in the code, if you find any, please let me know by pointing it in the thread
  • I have used CryptoJS library for SHA-256, RIPEMD-160 and HMAC-SHA512 algorithms.

Code Files:

File 1: mnemonic.js
Code:
//Generating random 128 bits. 128 - 256 bits can be used but for this tutorial we are strictly generating 128 bits entropy
const getRandomBytes = () => {
    const array = new Uint32Array(4); //creating Uint32 array having length = 4
    const randomBytes = crypto.getRandomValues(array); //Filling array with random 32-bits integers

    let binaryString = '';
    let hexString = '';
    randomBytes.forEach(byte => {
        let binChunk = byte.toString(2);
        binChunk = binChunk.length === 32 ? binChunk : '0'.repeat(32 - binChunk.length)+binChunk;
        let hexChunk = parseInt(binChunk,2).toString(16);

        binaryString += binChunk;
        hexString += hexChunk;
    })

    return [binaryString,hexString];
}

//Generating SHA-256 hash of random bytes for checksum
let [randomBits,randomBitsHex] = getRandomBytes();
const byteHash = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(randomBitsHex)).toString(); //SHA-256 Hash of random bytes
let checksum = parseInt(byteHash[0],16).toString(2); //Taking (entropy-length / 32) bits of SHA256 hash which in our case is 4 bits
checksum = checksum.length === 4 ? checksum : '0'.repeat(4 - checksum.length)+checksum; //Adding '0' bits if hex is smaller than '8' or '0b1000' in binary

//Adding checksum at the end of random bytes
randomBits += checksum;

//Splitting random bytes into segments of 11-bits length and storing in an array
const segmentArray = [];
let i = 0;
while (i < randomBits.length) {
    segmentArray.push(randomBits.substring(i,i+11));
    i += 11;
}

//Converting every 11-bits segment into decimal equivalent
const decimalArray = segmentArray.map(segment => parseInt(segment,2));

//Picking 'word' at position equivalent to decimal array from 'mnemonic words list' (words.js)
const mnemonicArray = decimalArray.map(decimal => wordsArray[decimal]);

//getMnemonic Function - This function will be called in front-end when user will create new seed
const getMnemonic = () => {
    return mnemonicArray.join(' '); //Converting mnemonic array into mnemonic string
}

Link: https://github.com/web-tricks/seed-guide/blob/main/mnemonic.js



File 2: p2pkh.js
Code:
//This function will generate Legacy bitcoin address (public key hash) using public key
const generateLegacyAddress = (publicKey) => {
    const keyHex = CryptoJS.enc.Hex.parse(publicKey);
    const ripedHashedKey = CryptoJS.RIPEMD160(CryptoJS.SHA256(keyHex)).toString();
    const mainRipeKeyString = '00'+ripedHashedKey;
    const mainRipeKey = CryptoJS.enc.Hex.parse(mainRipeKeyString);
    const doubleHashedKey = CryptoJS.SHA256(CryptoJS.SHA256(mainRipeKey)).toString();
    const checkSum = doubleHashedKey.substr(0, 8);
    const binaryAddress = mainRipeKeyString+checkSum;
    const arrayBinary = binaryAddress.match(/.{1,2}/g); //Converting serialization into array of every 2nd character
    const binaryUint = new Uint8Array(arrayBinary.map(hex => parseInt(hex,16))); //Converting hex array into uint8array to be used as input in base58 function
    
    return to_b58(binaryUint,bs58Chars);
}

Link: https://github.com/web-tricks/seed-guide/blob/main/p2pkh.js



File 3: p2sh.js
Code:
//This function will generate P2SH bitcoin address (P2WPKH-in-P2SH) using public key
const generateP2SHAddress = (publicKey) => {
    const keyHex = CryptoJS.enc.Hex.parse(publicKey);
    const ripeHash = CryptoJS.RIPEMD160(CryptoJS.SHA256(keyHex)).toString();

    const script = '0014'+ripeHash;
    const scriptHex = CryptoJS.enc.Hex.parse(script);
    const scriptRipeHash = '05'+CryptoJS.RIPEMD160(CryptoJS.SHA256(scriptHex)).toString();

    const doubleHashedKey = CryptoJS.SHA256(CryptoJS.SHA256(CryptoJS.enc.Hex.parse(scriptRipeHash))).toString();
    const checkSum = doubleHashedKey.substr(0, 8);

    const binaryAddress = scriptRipeHash+checkSum;

    const arrayBinary = binaryAddress.match(/.{1,2}/g); //Converting serialization into array of every 2nd character
    const binaryUint = new Uint8Array(arrayBinary.map(hex => parseInt(hex,16))); //Converting hex array into uint8array to be used as input in base58 function
    
    return to_b58(binaryUint,bs58Chars);
}

Link: https://github.com/web-tricks/seed-guide/blob/main/p2sh.js



File 4: ecc.js
Code:
//This file contains code for generating public key from private key using Elliptic Curve Cryptography
const Pcurve = BigInt('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F');

const Gx = BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240');
const Gy = BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424');

const G = [Gx, Gy];

const generatePublicKey = privateKey => {
    const ECCPoints = ECMultiply(G, privateKey);

    const checkKey = key => key.length < 64 ? '0'.repeat(64 - key.length)+key : key;

    const publicKeyX = checkKey(ECCPoints[0].toString(16));

    if (ECCPoints[1]%BigInt(2)===BigInt(1)) {
    return '03'+publicKeyX;
    } else {
    return '02'+publicKeyX;
    }
}

//mod inverse function
function modInverse(a, n) {

    a = (a % n + n) % n

    const dArray = [];
    let b = n;

    while(b) {
    [a, b] = [b, a % b];
    dArray.push({a, b});
    }

    if (a !== BigInt(1)) {
    return null;
    }

    let x = BigInt(1);
    let y = BigInt(0);

    for(let i = dArray.length - 2; i >= 0; --i) {
    [x, y] = [y,  x - y * BigInt(dArray[i].a / dArray[i].b)];
    }

    return (y % n + n) % n;
}

//mod of function
function modOf(a,b) {
    const r = ((a % b) + b)% b;
    return r;
}

//ECAdd - Elliptic Curve Addition Function
function ECAdd(a,b) {
    const lamAdd = modOf((b[1] - a[1]) * BigInt(modInverse(b[0] - a[0], Pcurve)), Pcurve);
    const x = modOf((lamAdd*lamAdd - a[0] - b[0]), Pcurve);
    const y = modOf((lamAdd*(a[0] - x) - a[1]), Pcurve);
    return [x, y];
}

//ECDouble - Elliptic Curve Point Doubling
function ECDouble(a) {
    const lamda = modOf(((BigInt(3)*a[0]*a[0])*(modInverse(BigInt(2)*a[1], Pcurve))), Pcurve);
    const x = modOf((lamda*lamda - BigInt(2)*a[0]), Pcurve);
    const y = modOf((lamda*(a[0] - x) - a[1]), Pcurve);
    return [x, y];
};

//ECMultiply - Ellptic Curve Multiplication
function ECMultiply(genPoint, pvtKey) {
    const scalarBinary = BigInt('0x'+pvtKey).toString(2);
    let GP = genPoint;

    for (let i=1; i < scalarBinary.length; i++) {
        GP = ECDouble(GP)
        if (scalarBinary[i] === '1') {
            GP = ECAdd(GP, genPoint);
        }
    }
    return GP;
}

Link: https://github.com/web-tricks/seed-guide/blob/main/ecc.js



File 5: bs58.js
Code:
//This javascript code for base58 encoding is taken from https://gist.github.com/diafygi/90a3e80ca1c2793220e5/
var to_b58 = function(B,A){var d=[],s="",i,j,c,n;for(i in B){j=0,c=B[i];s+=c||s.length^i?"":1;while(j in d||c){n=d[j];n=n?n*256+c:c;c=n/58|0;d[j]=n%58;j++}}while(j--)s+=A[d[j]];return s};
var bs58Chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';n*58+c:c;c=n>>8;d[j]=n%256;j++}}while(j--)b.push(d[j]);return new Uint8Array(b)};

Link: https://github.com/web-tricks/seed-guide/blob/main/bs58.js



File 6: address.js
Code:
//This function will take mnemonic code as the input and produce addresses
const detailsFromMnemonic = mnemonic => {

    // 1. Creating 'seed' from mnemonic code
    const salt = 'mnemonic'; //constant string 'mnemonic' used for salt in PBKDF2 function (custom passphrase could be used as well)
    const seed =  CryptoJS.PBKDF2(mnemonic, salt, {
        hasher:CryptoJS.algo.SHA512,
        keySize: 512 / 32,
        iterations:2048
    }).toString(); //using 2048 rounds of PBKDF2 key-stretching function

    // 2. Creating 'Master Private Key' and 'Chain Code' from 'seed'
    const hmacHash =  CryptoJS.HmacSHA512(CryptoJS.enc.Hex.parse(seed),'Bitcoin seed').toString();
    const masterPrivateKey = hmacHash.substr(0,64); //Left 256 bits of HMAC-512 hash
    const chainCode = hmacHash.substr(64,64); //Right 256 bits of HMAC-512 hash
    let masterPublicKey = generatePublicKey(masterPrivateKey);

    // 3. Generating childs using BIP-44 Derivation Path for LEGACY (Derivation Path - m/44'/0'/0'/0); - Hardened Child - 0x8000002c
        let {addresses: legacyAddresses, privateKeys: legacyPrivateKeys} = returnChild(masterPrivateKey,masterPublicKey,chainCode,'8000002c');
        //  Converting Public Key in the Array to Legacy Bitcoin Addresses
        legacyAddresses = legacyAddresses.map(publicKey => generateLegacyAddress(publicKey));

    // 4. Generating childs using BIP-49 Derivation Path for P2SH (Derivation Path - m/49'/0'/0'/0); - Hardened Child - 0x80000031
        let {addresses: p2shAddresses, privateKeys: p2shPrivateKeys} = returnChild(masterPrivateKey,masterPublicKey,chainCode,'80000031');
       //  Converting Public Key in the Array to P2SH Bitcoin Addresses
       p2shAddresses = p2shAddresses.map(publicKey => generateP2SHAddress(publicKey));
   
    // 5. Generating childs using BIP-84 Derivation Path for Bech32 (Derivation Path - m/84'/0'/0'/0); - Hardened Child - 0x80000054
        let {addresses: bech32Addresses, privateKeys: bech32PrivateKeys} = returnChild(masterPrivateKey,masterPublicKey,chainCode,'80000054');
       //  Converting Public Key in the Array to P2SH Bitcoin Addresses
       bech32Addresses = bech32Addresses.map(publicKey => generateBech32Address(publicKey));
       
    return {
        masterPrivateKey,
        masterPublicKey,
        legacyPrivateKeys,
        legacyAddresses,
        p2shAddresses,
        p2shPrivateKeys,
        bech32Addresses,
        bech32PrivateKeys
    }
}

//Function for Deriving Children based on Hardened Child
function returnChild(masterPrivateKey,masterPublicKey,chainCode,hardenedChild) {
    // First Level: m/H':
    const [firstChildPrivate,firstChildPublic,firstChildChain] = generatingChild(masterPrivateKey,masterPublicKey,chainCode,hardenedChild,'private');
    // Second Level: m/H'/0':
    const [secondChildPrivate,secondChildPublic,secondChildChain] = generatingChild(firstChildPrivate,firstChildPublic,firstChildChain,'80000000','private');
    // Third Level: m/H'/0'/0':
    const [thirdChildPrivate,thirdChildPublic,thirdChildChain] = generatingChild(secondChildPrivate,secondChildPublic,secondChildChain,'80000000','private');
    // Fourth Level: m/H'/0'/0'/0 - For main receiving addresses:
    const [fourthChildPrivate,fourthChildPublic,fourthChildChain] = generatingChild(thirdChildPrivate,thirdChildPublic,thirdChildChain,'00000000','public');

    // Fifth Level: This level will be used for addresses
    //  We will generate 10 addresses from m/H'/0'/0'/0/0 to m/H'/0'/0'/0/9 branch to be used as receiving addresses
    let addresses = [];
    const privateKeys = [];
    for (let i=0;i<10;i++) {
        const childSet = generatingChild(fourthChildPrivate,fourthChildPublic,fourthChildChain,'0000000'+i,'public');
        addresses.push(childSet[1]); //Pushing Public Key in the Array
        privateKeys.push(childSet[0]); //Pushing Private Key in the Array
    }

    return {
        addresses,
        privateKeys
    }
}

//Function to generate child private key, child public key and child chain code
function generatingChild(parentPrivateKey, parentPublicKey, parentChainCode,index,type) {
    let parentPrivate = parentPrivateKey.length === 64 ? parentPrivateKey : '0'.repeat(64-parentPrivateKey.length)+parentPrivateKey;
    const keyToUse = type === 'private' ? '00'+parentPrivate : parentPublicKey; //Use private key if hardened-index else public key
    const hmacHash = CryptoJS.HmacSHA512(CryptoJS.enc.Hex.parse(keyToUse+index),CryptoJS.enc.Hex.parse(parentChainCode)).toString();
    const [leftBits,childChainCode] = separateKeyChain(hmacHash);
    const N = '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'; //As defined in secp256k1 ecc
    let childPrivateKey = (BigInt('0x'+parentPrivate) + BigInt('0x'+leftBits)) % BigInt(N);
    childPrivateKey = childPrivateKey.toString(16); //Converting from decimal to hex
    const childPublicKey = generatePublicKey(childPrivateKey); //Using ECC function taken from 'ecc.js' file

    return [childPrivateKey,childPublicKey,childChainCode];
}

//Function to be used in generatingChild function to separate hash into private key and chain code
function separateKeyChain(hmacHash) {
    const privateKeyPart = hmacHash.substr(0,64);
    const chainCodePart = hmacHash.substr(64,64);
    return [privateKeyPart,chainCodePart];
}

Link: https://github.com/web-tricks/seed-guide/blob/main/address.js



File 7: words.js

Download this file directly from: https://github.com/web-tricks/seed-guide/blob/main/words.js



File 8: index.html
Code:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
    <title>Bitcoin Addresses from Mnemonic Code</title>
    <style>
        body {
            font-family:Georgia, 'Times New Roman', Times, serif;
            text-align: center;
        }
        .seed {
            width: 300px;
        }
        #display {
            font-family: 'Times New Roman', Times, serif;
        }
    </style>
</head>
<body>
    <h1>Deriving Bitcoin Address from Seed Phrase (Mnemonic Seed)</h1> 
    <p><button id="generate_random">Generate Random Seed</button></p>
    <h2>OR</h2>
    Enter your Seed:
    <form id="import">
        <input class="seed"><input type="submit" value="generate addresses">
    </form>
    <div id="display"></div>
    <script src="bs58.js"></script>
    <script src="ecc.js"></script>
    <script src="p2pkh.js"></script>
    <script src="p2sh.js"></script>
    <script src="bech32.js"></script>
    <script src="words.js"></script>
    <script src="mnemonic.js"></script>
    <script src="address.js"></script>

    <script>
        let mnemonic;

        document.getElementById('generate_random').addEventListener('click', () => {
            mnemonic = getMnemonic();
            prepareDisplay();
        });

        document.getElementById('import').addEventListener('submit', e => {
            e.preventDefault();
            mnemonic = document.querySelector('.seed').value;
            prepareDisplay();
        });

        function prepareDisplay() {
            const {masterPrivateKey,masterPublicKey,legacyPrivateKeys,
            legacyAddresses,p2shAddresses,p2shPrivateKeys,bech32Addresses,
            bech32PrivateKeys} = detailsFromMnemonic(mnemonic);

            let html = `
                <p>Mnemonic Code (Seed Phrase): ${mnemonic}<br></p>
                <p>Master Private Key: ${masterPrivateKey}<br></p>
                <p>Master Public Key: ${masterPublicKey}<br></p>
            `;

            html += `<p>Legacy Addresses (first 10)<br>`;
            legacyAddresses.forEach((address,index) => {
                html += `${index+1}. ${address} - Private Key: ${legacyPrivateKeys[index]}<br>`;
            });

            html += `</p>`;

            html += `<p>P2SH Addresses (first 10)<br>`;
            p2shAddresses.forEach((address,index) => {
                html += `${index+1}. ${address} - Private Key: ${p2shPrivateKeys[index]}<br>`;
            });

            html += `</p>`;

            html += `<p>Bech32 Addresses (first 10)<br>`;
            bech32Addresses.forEach((address,index) => {
                html += `${index+1}. ${address} - Private Key: ${bech32PrivateKeys[index]}<br>`;
            });

            html += `</p>`;

            document.getElementById('display').innerHTML = html;
        }
    </script>
</body>
</html>

Link: https://github.com/web-tricks/seed-guide/blob/main/index.html



File 9: bech32.js
Code:
//This function will generate P2SH bitcoin address (P2WPKH-in-P2SH) using public key
const generateBech32Address = (publicKey) => {
    const bech32schema = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';

    const keyHex = CryptoJS.enc.Hex.parse(publicKey);
    const ripeHash = CryptoJS.RIPEMD160(CryptoJS.SHA256(keyHex)).toString();

    let binString = BigInt('0x'+ripeHash).toString(2);
    binString = binString.length === 160 ? binString : '0'.repeat(160-binString.length)+binString;

    const decArray = binString.match(/.{1,5}/g).map(binary => parseInt(binary,2));
    decArray.unshift(0);

    const checkSum = createChecksum(decArray);

    const hexString = decArray.map(decimal => ('00'+decimal.toString(16)).substr(-2)).join('');

    let address = '';

    (hexString+checkSum).match(/.{1,2}/g).forEach(hexVal => {
        address += bech32schema[parseInt(hexVal,16)];
    });
   
    return 'bc1'+address;
}

//Checksum generation using BCH Codes
function createChecksum(decArr) {
    const GEN = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
    let chk = 1

    let decArray = [3,3,0,2,3].concat(decArr)
    decArray = decArray.concat([0,0,0,0,0,0]);
   
    decArray.forEach(dec => {
        let b = chk >> 25;
        chk = (chk & 0x1ffffff) << 5 ^ dec;

        for (let i=0;i<5;i++) {
            chk ^= ((b >> i) & 1) ? GEN[i] : 0;
        }
    });

    const polymod = chk ^ 1;

    const returnVal = [];

    for (let v=0;v<6;v++) {
        returnVal.push((polymod >> 5 * (5 - v)) & 31)
    }

    return returnVal.map(val => ('00'+val.toString(16)).substr(-2)).join('');
}

Link: https://github.com/web-tricks/seed-guide/blob/main/bech32.js



Save all files in one folder and then open index.js file in your browser to run the code.
14  Other / Beginners & Help / [Full Guide+Code]Seed Phrase & The Process of Deriving Bitcoin Addresses from It on: February 09, 2021, 08:57:10 PM
Earlier Bitcoin Wallet used to be a bunch of private keys. In order to use new address, user had to generate new private key which made the whole process cumbersome because user had to backup each and every private key. Hierarchical Deterministic (HD) wallet made the process easier. Deterministic wallet means the wallet uses a single starting point to derive all the addresses. That single starting point is known as 'mnemonic seed' or 'seed phrase'. Today, more than 95% non-custodial wallets generate addresses deterministically and if they aren't, you shouldn't be using those wallets.

Considering that the seed phrase has become integral part of Bitcoin Wallet, I will explain the whole process on how bitcoin addresses are derived from seed phrase along-with Javascript code so you can easily test the process in your computer without downloading or installing any utility.  

Table of Contents
1. Generate Random Sequence or Entropy
2. Create Checksum and Prepare Final Sequence
3. Convert Sequence into Mnemonic Codes
4. PBKDF2 Key-Stretching Function
5. Master Private Key, Master Public Key and Chain Code
6. Derivation Path and BIP-44
7. Child Private Key Derivation
8. Generate Bitcoin Addresses from Private Keys
9. Javascript Codes

1. Generate Random Sequence or Entropy

Earlier I said that the mnemonic (or seed phrase) is the starting point of the wallet which may not be entirely true. In order to derive mnemonic, we first need to generate entropy. In easier words, entropy is nothing but the measure of randomness. In order to secure wallet, we need it to be based on something unpredictable, hence entropy of 128-256 bits is used. The easiest way to generate entropy is by flipping the coin. Take a coin and toss it 128 times, write 0 when heads come while write 1 when tails come. After 128 flips, you will have the random sequence of 0s and 1s which is your entropy. You can do the same 256 times to increase the security of your wallet (longer the entropy, higher the security). Check the image below to understand the process better:



The 0 and 1 sequence you see above is the distinct point. This should be generated as random as possible. If weak random generator is used then hackers can easily brute-force your sequence and steal the funds.

2. Create Checksum and Prepare Final Sequence

Now, as we have the 128-bit entropy, we need to generate checksum. Checksum is nothing but a fingerprint attached at the end of something to ensure user has made no mistake is copying that thing. In our case, we will generate fingerprint of our entropy. As defined in BIP-39, we take SHA-256 hash of the entropy as the fingerprint. Before moving forward, let's convert our entropy from Base2 to Base16 or hexadecimal. Base2 means we use 2 symbols to express our number, as we saw in Step 1, those numbes are '0' and '1'. Similarly, Base16 (or hexadecimal) uses 16 symbols to express the number, those are: 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f. Check the image below to understand how conversion works:



You can see that 0001 in Base2 is equal to 1 in hexadecimal, 0010 is equal to 2 and so on. So, our entropy in hexadecimal is represented as 91d3785bf884c639f600b3e587083265. But important point here is that both are same, just representation is different.

Back to checksum now, like I said earlier, SHA-256 of the entropy is used as checksum, let's generate the SHA-256 of our entropy:

SHA-256 hash of 0x91d3785bf884c639f600b3e587083265 = effdb98e4c4ac27c670f704c39a2e0ba8b85bc4561a7a02a6297e465ed155d30

The hash is 256-bit long number represented by 64 hexadecimal characters. In other words, each hexadecimal character represents 4 bits. As per BIP-39, instead using the whole hash, only first (entropy length / 32) bits of the hash are used as checksum. In our case, the length of entropy is 128 which when divided by 32 gives 4. So, we will only take first four bits of the hash as checksum. If the length of your entropy is 256, checksum would be 256/32 or first 8 bits of the hash.

As I said earlier, each hexadecimal character represents four bits, the first four bits of our hash in hexadecimal are represented by 'e'. So, our checksum is 'e' in hexadecimal and 1110 in Base2 (or binary). Now, we append checksum at the end of the sequence which will make our final sequence in hexadecimal as, 0x91d3785bf884c639f600b3e587083265e. Or in Base2 as:




3. Convert Sequence into Mnemonic Codes

Now the length of the sequence is 132 bits. Next step involves splitting the sequence into the chunk of 11 bits. Since, our sequence is of 132 which when divided by 11 gives 12, so we will get 12 chunks. We will get 24 chunks if 256-bit entropy is used.

Here are the chunks of our entropy:
10010001110
10011011110
00010110111
11110001000
01001100011
00011100111
11011000000
00010110011
11100101100
00111000010
00001100100
11001011110

As you can notice, each chunk is a binary number. The lowest value of the chunk can be 00000000000 which is 0 in decimal. Whereas, maximum value can be 11111111111 which is 2047 in decimal. So, each chunk is valued between 0-2047. BIP-39 defined 2048 words, each word representing one number from 0 to 2047. I have prepared a table so you can see which word is used for which value, visit the link below to view the table:


From the table, you can see that the decimal values of our chunks are: 1166, 1246, 183, 1928, 611, 231, 1728, 179, 1836, 450, 100, 1630

Picking the adjacent words from the link, we got the following mnemonic code:

Code:
mushroom orange black valve erase brother submit biology tortoise debate arrive slim


4. PBKDF2 Key-Stretching Function

Password-based Key Derivation Function 2 (or PBKDF2) is used as a security measure in the process. This function allows the use of 'passphrase' to further increase the security of our mnemonic code. You can read more about PBKDF2 function on: Wikipedia.

In our bitcoin address derivation process, PBKDF2 is used to stretch mnemonic code by using 2048 rounds of HMAC-SHA512 algorithm. The algorithm takes two parameters, one is mnemonic code and second is salt. If user decides to opt for no passphrase then salt is the string with the value - 'mnemonic'. But, if user decides, let say, 'webby' as the passphrase. Then, salt will become- 'mnemonicwebby'. We concat passphrase at the end of 'mnemonic' string in salt.

Hence, our PBKDF2 function will become:

Code:
DK = PBKDF2(PRF, Password, Salt, c, dkLen)

Putting value for: PRF, Password, Salt, c and dkLen:

DK = PBKDF2(HMAC, 'mushroom orange black valve erase brother submit biology tortoise debate arrive slim', 'mnemonic', 2048, 64)

where, PRF is pseudorandom function (here HMAC)
Password is our mnemonic code
Salt is string 'mnemonic' without any passphrase
c is the number of iteration. In our case, 2048
dkLen is the desired length of derived key (we want 512-bit seed so we selected 64 byte since 1 byte = 8 bits)

DK refers to the final key or seed we derived from the process. In our case, we will get 512-bit value as the result. The key for our mnemonic code with no passphrase is:
Code:
65729d81d461591bac7384dea43dbd44438053cd1fdc113e0769c49c5fde025ba331eed2077497634e619948437d0448e769a86c0cbbecf01b13fd53540743b3


5. Master Private Key, Master Public Key and Chain Code

As I discussed in the starting of the thread, the main purpose of using seed phrase is to get hierarchical tree like structure, where each private or public key is derived from its parent and can derive its children. Master Private Key is the top of the hierarchy. It is a private key at first level with no parent.

We have generated DK or 512-bit seed in the last step. This seed will now be used in HMAC-SHA512 function to derive private key and chain code. HMAC-SHA512 function takes two parameters - message and secret key. In our case, 512-bit seed from the last step is message and as defined in BIP-32, string 'Bitcoin seed' is used as secret key. So,

HMAC(seed, 'Bitcoin seed') = Hash

The resulting hash will be a 512-bit value. In our case, it is the following:
Code:
a0ccf14c939faa07b896cd5fb306a37fb3f9cb041196c5364d0cca9dbd82e53a5bc9d1368631ae579f02ed8e46a56dd9dd9de8ac59e3c4e18247ff96988bdf1f

Note that the length of the output is 512 bits or 128 hexadecimal characters. The first 256 bits (represented by the first 64 hexadecimal characters) will become our Master Private Key whereas next 256 bits will become our Chain Code.

Hence,
Code:
Master Private Key: a0ccf14c939faa07b896cd5fb306a37fb3f9cb041196c5364d0cca9dbd82e53a
Chain Code: 5bc9d1368631ae579f02ed8e46a56dd9dd9de8ac59e3c4e18247ff96988bdf1f

Master Public Key can be derived from Master Private Key using Elliptic Curve Cryptography. I have written detailed thread on ECC. You can follow this thread: THE THREAD and see how public key is derived from private key. Process is same for the Master Public Key as well.

Using the same logic,
Code:
our Master Public Key: 03d1cc1f6bdea4d17eb7f2573d676f9ddb087f8b784c912c4466407781d8acfe38


6. Derivation Path and BIP-44

To easily understand the meaning of derivation path, you can assume it as a map which guides us how should be go through the children from the master private key to finally reach the bitcoin address. BIP-44 defines the following path for Bitcoin Mainnet:

Code:
Path format: m / purpose' / coin_type' / account' / change / address_index

Bitcoin Main-net format: m / 44' / 0' / 0' / 0 / address_index

To understand the above, first look at the image below:



It's like we will go to the master private key and ask, who is your 45th hardened child. Then we will go to the 45th child and ask it, who is your first hardened child. Then we will go to the first hardened child of the first hardened child of the master private key and ask it who is your first child. Then we will go and catch the first child and take its children one-by-one as our private keys. First child will become our first private key which will be used to derive our first bitcoin address and so on.

Now you maybe wondering what's the difference between hardened child and normal child. When we say first hardened child, it's actually (231+1)th child. For easy understanding, we replace 231 and use the symbol of prime ( ' ). So, 231+1 or 2147483649th child of the parent is first hardened or 0' child. (Notice the sign of prime at the right top of 0)

For more serious discussion about Derivation Path, check this thread from Blue Snow: https://bitcointalk.org/index.php?topic=5243350

7. Child Private Key Derivation

Okay, now as we know which child keys are to be derived, let's see how child key is derived:

To derive the child key, again HMAC-SHA512 hashing algorithm is used. As we discussed earlier, HMAC-SHA512 algorithm requires 2 params - message and secret key. Here, message is our master private or public key concatenated with the child number (also known as child index) and secret key is the chain code. So,

Hash = HMAC(master key + index, chain code)

Important Point: When we are deriving hardened child, master private key will be used as message. Whereas, master public key will be used in case we are deriving normal child.

Now let's get started with the process:

LEVEL 1: Deriving 45th hardened child of the Master Key (Since it's hardened, Master Private Key will be used)
Code:
Master Private Key = a0ccf14c939faa07b896cd5fb306a37fb3f9cb041196c5364d0cca9dbd82e53a (taken from the fifth step)
Index = 8000002c (value of 2147483692 i.e. 2^31+44 in hexadecimal)
Chain Code = 5bc9d1368631ae579f02ed8e46a56dd9dd9de8ac59e3c4e18247ff96988bdf1f (taken from the fifth step)

So,
Message = 00a0ccf14c939faa07b896cd5fb306a37fb3f9cb041196c5364d0cca9dbd82e53a8000002c
(important thing to notice here, the length of message should be 296 bits. Since, the length of master private key is 256 bits and index is 32 bits,
we need additional 8 bits, hence we added 00 i.e. 8 empty bits in the starting)

Key = 5bc9d1368631ae579f02ed8e46a56dd9dd9de8ac59e3c4e18247ff96988bdf1f

HMAC(message, key) = 7fc9ce32a6aeffbeaf5057f266f0d6ed6383ed84f21c96d53c0c1e3838a87e2481d4b120fcd3a11837e5d035fc508bb8b31c47285fdd7506d8d264144b4d8df7

Note, we got the output of 512 bits. Similar to what we discussed in fifth step, the left 256 bits of the output will be used for the private key of our 45th hardened child and right 256 bits will become the chain code of the child. The left 256 bits are assumed as a hexadecimal number and added to the parent private key. Then we take the modulus of the addition with 'n' parameter as defined by SECG in this document: SECG Vol 2

Code:
Left 256 bits = 7fc9ce32a6aeffbeaf5057f266f0d6ed6383ed84f21c96d53c0c1e3838a87e24
Parent Private Key =  a0ccf14c939faa07b896cd5fb306a37fb3f9cb041196c5364d0cca9dbd82e53a
N = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 (n as defined)

Private Key of 45th Hardened Child of Master Private Key = ( Left 256 bits + Parent Private Key ) % N
Private Key of 45th Hardened Child of Master Private Key = 2096bf7f3a4ea9c667e7255219f77a6e5ccedba2546abbcfc9468a4925f5221d

Chain Code of 45th Hardened Child of Master Private Key = 81d4b120fcd3a11837e5d035fc508bb8b31c47285fdd7506d8d264144b4d8df7 (right 256 bits)


LEVEL 2: Deriving first hardened child of the Level 1 Child (Since it's hardened, Private Key will be used)
Code:
Private Key = 2096bf7f3a4ea9c667e7255219f77a6e5ccedba2546abbcfc9468a4925f5221d
Index = 80000000 (value of 2147483648 i.e. 2^31 in hexadecimal)
Chain Code = 81d4b120fcd3a11837e5d035fc508bb8b31c47285fdd7506d8d264144b4d8df7

So,
Message = 002096bf7f3a4ea9c667e7255219f77a6e5ccedba2546abbcfc9468a4925f5221d80000000
Key = 81d4b120fcd3a11837e5d035fc508bb8b31c47285fdd7506d8d264144b4d8df7

HMAC(message, key) = dee4c4cb625b27f231194cf3befea6e67a73122f77a748b987fded5333ca63f7d665636fd64693411687f8d4deeb8382d14deb3d9937e72635e77af48c4da4e6

Left 256 bits = dee4c4cb625b27f231194cf3befea6e67a73122f77a748b987fded5333ca63f7
Parent Private Key =  2096bf7f3a4ea9c667e7255219f77a6e5ccedba2546abbcfc9468a4925f5221d
N = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 (n as defined)

Private Key of first hardened child of Level 1 Child = ( Left 256 bits + Parent Private Key ) % N
Private Key of first hardened child of Level 1 Child = ff7b844a9ca9d1b899007245d8f62154d741edd1cc1204895144779c59bf8614

Chain Code of first hardened child of Level 1 Child: d665636fd64693411687f8d4deeb8382d14deb3d9937e72635e77af48c4da4e6

LEVEL 3: Deriving first hardened child of the Level 2 Child (Since it's hardened, Private Key will be used)
Code:
Private Key = ff7b844a9ca9d1b899007245d8f62154d741edd1cc1204895144779c59bf8614
Index = 80000000 (value of 2147483648 i.e. 2^31 in hexadecimal)
Chain Code = d665636fd64693411687f8d4deeb8382d14deb3d9937e72635e77af48c4da4e6

So,
Message = 00ff7b844a9ca9d1b899007245d8f62154d741edd1cc1204895144779c59bf861480000000
Key = d665636fd64693411687f8d4deeb8382d14deb3d9937e72635e77af48c4da4e6

HMAC(message, key) = 2839a8f276409794544cdc9f4d2748a3ea3ca988b64f82e72414d67dedaf751bfb106a1896e38ddc80b3d3b4fdaba9b003d1e6caa08c6cbbdc5d63fa6836b613

Left 256 bits = 2839a8f276409794544cdc9f4d2748a3ea3ca988b64f82e72414d67dedaf751b
Parent Private Key =  ff7b844a9ca9d1b899007245d8f62154d741edd1cc1204895144779c59bf8614
N = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 (n as defined)

Private Key of first hardened child of Level 2 Child = ( Left 256 bits + Parent Private Key ) % N
Private Key of first hardened child of Level 2 Child = 27b52d3d12ea694ced4d4ee5261d69fa06cfba73d318e734b586ef8d7738b9ee

Chain Code of first hardened child of Level 2 Child: fb106a1896e38ddc80b3d3b4fdaba9b003d1e6caa08c6cbbdc5d63fa6836b613

LEVEL 4: Deriving first normal child of the Level 3 Child (Since it's normal, Public Key will be used)
Code:
Private Key = 27b52d3d12ea694ced4d4ee5261d69fa06cfba73d318e734b586ef8d7738b9ee
Public Key = 03fc371a6939557697a438cca5c81fc899d611d41f605d1b6d1a8096fd5e3e0343 (using ECC)
Index = 00000000 (value of 0 in hexadecimal)
Chain Code = fb106a1896e38ddc80b3d3b4fdaba9b003d1e6caa08c6cbbdc5d63fa6836b613

So,
Message = 03fc371a6939557697a438cca5c81fc899d611d41f605d1b6d1a8096fd5e3e034300000000
(Since we are using Public Key which is already of 264 bits, we needn't concat additional bits in the starting)

Key = fb106a1896e38ddc80b3d3b4fdaba9b003d1e6caa08c6cbbdc5d63fa6836b613

HMAC(message, key) = bd63f3fe2daf72bd61d983477a8330e377ecc1fa664bee4a90da90003de9ef8c29a2907541b35ab602c72d52c330184a2e7908060b98acca9b17ebfaea0135a8

Left 256 bits = bd63f3fe2daf72bd61d983477a8330e377ecc1fa664bee4a90da90003de9ef8c
Parent Private Key =  27b52d3d12ea694ced4d4ee5261d69fa06cfba73d318e734b586ef8d7738b9ee
N = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 (n as defined)

Private Key of first normal child of Level 3 Child = ( Left 256 bits + Parent Private Key ) % N
Private Key of first normal child of Level 3 Child = e519213b4099dc0a4f26d22ca0a09add7ebc7c6e3964d57f46617f8db522a97a

Chain Code of first hardened child of Level 3 Child: 29a2907541b35ab602c72d52c330184a2e7908060b98acca9b17ebfaea0135a8


LEVEL 5: Deriving first 3 normal children of the Level 4 Child (Since it's normal, Public Key will be used)
Code:
Private Key = e519213b4099dc0a4f26d22ca0a09add7ebc7c6e3964d57f46617f8db522a97a
Public Key = 0321bd38eb2f97c56762b82f22e9677d6aa205a73664b93aaf8ed087bd9fc26420 (using ECC)
Index = 00000000, 00000001 and 00000002
Chain Code = 29a2907541b35ab602c72d52c330184a2e7908060b98acca9b17ebfaea0135a8

So,
Message1 = 0321bd38eb2f97c56762b82f22e9677d6aa205a73664b93aaf8ed087bd9fc2642000000000
Message2 = 0321bd38eb2f97c56762b82f22e9677d6aa205a73664b93aaf8ed087bd9fc2642000000001
Message3 = 0321bd38eb2f97c56762b82f22e9677d6aa205a73664b93aaf8ed087bd9fc2642000000002

Key = 29a2907541b35ab602c72d52c330184a2e7908060b98acca9b17ebfaea0135a8

HMAC(message1, key) = a8764acda4ebc575ff750e113353a805186febf32372deb4fab9ed180a7b4db3a3e1295ec9c664d73d77841b263d019306d914e431fdc84973cf53abaa0883cb
HMAC(message2, key) = fb58f1f53183d06aed97ba85ad30fc89d4500bb3c5d47880cc96c368f044618743a1580a9757af12b8597450ff8a5b37e9a51660b0a30e672b736464f4cdb7d0
HMAC(message3, key) = b30db2ea8ad0e61c43acf2052ecc0d3c174cf5a57655ba038ba8894f3bc2f0d8c140e5f51589c16e3d3502b08fc005e8a9acfa5a56dda2e08b520b3179c1f163

Left 256 bits of HMAC1 = a8764acda4ebc575ff750e113353a805186febf32372deb4fab9ed180a7b4db3
Left 256 bits of HMAC2 = fb58f1f53183d06aed97ba85ad30fc89d4500bb3c5d47880cc96c368f0446187
Left 256 bits of HMAC3 = b30db2ea8ad0e61c43acf2052ecc0d3c174cf5a57655ba038ba8894f3bc2f0d8

Parent Private Key =  e519213b4099dc0a4f26d22ca0a09add7ebc7c6e3964d57f46617f8db522a97a
N = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 (n as defined)

Private Key of first normal child of Level 4 Child = 8d8f6c08e585a1804e9be03dd3f442e3dc7d8b7aad8f13f881490e18ef67b5ec (to be used for deriving first bitcoin address)
Private Key of second normal child of Level 4 Child = e0721330721dac753cbe8cb24dd19768985dab3b4ff0adc45325e469d530c9c0 (to be used for deriving second bitcoin address)
Private Key of third normal child of Level 4 Child = 9826d425cb6ac22692d3c431cf6ca81adb5a952d0071ef471237aa5020af5911 (to be used for deriving third bitcoin address)



8. Generate Bitcoin Addresses from Private Keys

In the last step, we derived 3 private keys at Level 5 using index 00000000, 00000001 and 00000002. If you want to derive more private keys in the hierarchy, just keep on incrementing index by 1. So, 00000003 will be used for next private key and so on. Also, remember that this is hexadecimal number so after  00000009, next index will be 0000000a, not 00000010.

Now, let's generate the bitcoin addresses from our private key. I have already created a thread explaining how to generate Legacy addresses (starting with '1') from private key in detail here: How Bitcoin Addresses are generated? Understand the Math behind Bitcoin

You can follow the above thread and you will be able to generate first 3 Legacy Bitcoin Addresses of the hierarchy using private keys from Step 7, which will be:
Quote
1MbJqqvN8ZPYsUch45HdRAxKbH6bJeGfZi
1GMpMNYwhb7Wvu8q1Zy52MtZUGWvLgCXak
12fv5eg3kzBgZQy7ue2yYmC9xXohmKWGR3

I will use the current thread to explain how to generate P2SH Address. P2SH is very different from the P2PKH (or Legacy) address. In Legacy address, we simply generate the hash of the public key and use it as the address. But in P2SH, we first create a script, then generate hash of the script. Then, transaction is made to the script. Now, script can literally be anything. Sender of the transaction don't have to know what does the script mean. Bitcoin has its own scripting language and the script has defined many opcodes such as OP_ADD, OP_EQUAL and many more. So, I can literally create a script, let say, 'what when added to 3 makes 5'. Create hash of this script and use it as P2SH Address. Then the payment made to that P2SH address can be spent by providing original script i.e. 'what when added to 3 makes 5' and solution script i.e. '2' along with the hash.

P2SH can be used to create a lot more complex scripts but one of the most common type of P2SH is our P2WPKH-in-P2SH. It simply means using P2PKH in the P2SH script. This is the type of addresses you see while creating a wallet (the ones starting with '3'). Now, let's see, how are these created:

The scheme for P2WPKH-in-P2SH format is defined in BIP-49. In step 6, we discussed that the 45th hardened child of Master Private Key is used in the hierarchy. That's true for Legacy addresses but for P2WPKH-in-P2SH, we use the 50th hardened child, so, derivation path becomes:
Code:
m / 49' / 0' / 0' / 0 / address_index

Except this, rest of the process is same as discussed in Step 6 and 7. I have repeated the Step 7 with our Master Private Key, i.e. a0ccf14c939faa07b896cd5fb306a37fb3f9cb041196c5364d0cca9dbd82e53a and got the following three private keys as the first 3 normal child of m/49'/0'/0'/0 path i.e. Level 5:
Code:
Private Key of first normal child of Level 4 Child = 26e1061459e7961eeac018efa765339d785bd30de91f8fade64c639b275d74c4 (to be used for deriving first bitcoin address)
Private Key of second normal child of Level 4 Child = 501a42ccd834bf61c211f5277bcbebe4120eea952efc91fd71125f61a1e7eec4 (to be used for deriving second bitcoin address)
Private Key of third normal child of Level 4 Child = 13ae95a5d643b9ebe355d103679ad4bcf3863efef78873f4e4f20a57cf044a51 (to be used for deriving third bitcoin address)

Using ECC, I got the following Public Keys (second reminder, if you wanna know how public key is derived from private key, check out my thread I mentioned in Step 5):
Code:
Public Key of first normal child of Level 4 Child = 021549dd72d89cbc844bb74ab6247239cf60d184cbfb0cfc4d024150a4985412fe (to be used for deriving first bitcoin address)
Public Key of second normal child of Level 4 Child = 02e589abcbdbcf7b9746d1e2f5d97e5d2836c82b5910c5716f094801c0178ecfc2 (to be used for deriving second bitcoin address)
Public Key of third normal child of Level 4 Child = 020711fb2e08e67c13bcfb2cca60ff5ac3b7c6fb9e902722127ef776e5d2db6046 (to be used for deriving third bitcoin address)

First check the image below to understand how public key is converted into Bitcoin Address:



Now time for the explanation:

Firstly, we create SHA-256 hash of the public key:
Code:
SHA-256(public key) = Hash

SHA-256(021549dd72d89cbc844bb74ab6247239cf60d184cbfb0cfc4d024150a4985412fe) = 189a3015638daa02871973bf840b434aad92cb71775b65680acd266b81e85e3f

Then, we create ripemd160 hash of the sha256 hash:
Code:
RIPEMD160(hash) = Hash160

RIPEMD160(189a3015638daa02871973bf840b434aad92cb71775b65680acd266b81e85e3f) = 2bf545ff88c159408f5ba759f99e78566763fe1a

Then, we concat 0x0014 before the hash:
Code:
serialization = 0x0014 + Hash160

serialization = 00142bf545ff88c159408f5ba759f99e78566763fe1a
Note: 0x00 represent OP_0 and 0x14 is the size of the data to be pushed on stack in hexadecimal. Hence, OP_0 PushData<hash> represents our P2WPKH-P2SH script.

Now, as we have our script, next step involves creating hash of the script:
Code:
SHA-256(script) = Hash

SHA-256(00142bf545ff88c159408f5ba759f99e78566763fe1a) = c2d24e021347966656ed4b0312f9b3a49498c257294bd75e9bc84ba8353deb9a

Then,
RIPEMD160(hash) = Hash160

RIPEMD160(c2d24e021347966656ed4b0312f9b3a49498c257294bd75e9bc84ba8353deb9a) = 2d7193893e4143fc11bb69c7f004452198bdf6cd

Then add 0x05 before the hash160 i.e. encoding byte for script hash
Code:
serialization = 0x05 + Hash160

serialization = 052d7193893e4143fc11bb69c7f004452198bdf6cd

Creating checksum of the hash
Code:
checksum = first four bytes of SHA-256(SHA-256(hash))

SHA256(SHA256(052d7193893e4143fc11bb69c7f004452198bdf6cd)) = dcd3b30cd36dcef8265fbe414e435fc7841ced941f93ef86afd86e344c4a700e
First four bytes = dcd3b30c

Adding checksum at then end of hash and encoding it into Base58:
Code:
final serialization = 052d7193893e4143fc11bb69c7f004452198bdf6cddcd3b30c

Base58(052d7193893e4143fc11bb69c7f004452198bdf6cddcd3b30c) = 35qJPbZX23wt3uuB9nz4pxhoouUfG28zxB

Hence, 35qJPbZX23wt3uuB9nz4pxhoouUfG28zxB is our first Bitcoin Address in the hierarchy.
15  Economy / Games and rounds / Re: 🎡 GOSU Roll Hunt @ BC.Game 🎲 $400+ Dice Contest 🎲 72 hours! 🎡 ⭐ BTCGOSU ⭐ on: February 07, 2021, 02:42:09 PM
Username: webtricks (no longer Prize Langston shit)

Server Seed: 1b187cdf3c57fcc35ce8e0273c7e5619acf4357b3c7f91ae76d1244919c84bc1
Client Seed: hawameinhokemalang

Nonce: 7367, 8150, 8344, 15406, 15900, 23657, 45362, 49266

Bet IDs:
1275092038317180
1275092038324937
1275092038308647
1275092038309430
1275092038316686
1275092038350546
1275092038346642
1275092038309624

Tweet Link: https://twitter.com/Bitcoin_Bullet/status/1358425423701417985 (made only one. It doesn't make sense to make tweets for every hit).


16  Alternate cryptocurrencies / Altcoin Discussion / Re: I want to send ETH from exchange to Binance Smart Chain then to erc-20 wallet on: February 06, 2021, 08:35:28 AM
I am trying to make withdrawal using Smart Chain to my Trust wallet Smart Chain address that supports Ether since the address are both the same (BSC and ERC-20 have the same address).
Then make transfer of the Eth back to my normal erc-20 which will be cheaper instead of paying 0.05 eth to exchange directly.

Is this possible and has anyone try it before?

Nope, both chains are non-compatible. It's no different than saying, 'can we transfer BTC to ETH address?'.

If you withdraw your coins to BSC chain, you can only send it to other address on BSC chain or back to Binance.
17  Economy / Economics / Re: The Bitcoin Price Paradox on: February 06, 2021, 07:44:40 AM
Ah! You disappointed me. Reading all way down, I thought you were going to put some interesting economic flaw in bitcoin pricing. But in the end, it turned out that the thread was just a shill for Bitflate and you were advocating the inflationary supply of bitcoin all along. You do realize that your argument is hilarious, right?
18  Bitcoin / Bitcoin Discussion / Re: Bitcoin Fork / Swap? on: February 06, 2021, 06:56:35 AM
Hello,
is it possible, that there will be a bitcoin fork or swap in the future,
and all who forget to swap or follow the fork could lose their bitcoins?

Was there such a situation since bitcoin exists?

Or is it safe to store the bitcoins in the electrum wallet,
and we don`t have to care about anything?

Hard fork simply means change in the network consensus rules such that the nodes no longer accept transactions/blocks based on old rules and vice-versa. There is no notable and intentional hard fork in Bitcoin Network so far. However, there were few patches to eradicate network vulnerabilities from time to time.

But since you are just holding bitcoins on a non-custodial wallet, you needn't worry about anything. In fact, you are not storing bitcoins on Electrum wallet. Your coins are stored on blockchain associated with your private keys. If you have safely backed-up your seed phrase (or private key) then your coins are safe. Even if, Electrum doesn't upgrade to the new consensus rule in the event of any future chain split, you can simply import your seed in a compatible wallet and spend coins on a new chain.

Only problem may come if you are using custodial wallet. In that case, your wallet may not upgrade to the new rules and you will be unable to spend coins on new chain.
19  Bitcoin / Bitcoin Discussion / Re: India makes ownership of Bitcoin criminal offense - How to respond? on: February 02, 2021, 02:13:28 PM
~~
One thing that I'm not sure how users from India ill take it.
The bad news is that obviously the one above, the good news is that the market doesn't care which brings us the second bad news, seems like the Indian influence on the price is null to negative.

No, it isn't like that. There are around 8-9M Indian crypto traders who bought or sold cryptos at least once in last 12 months. The number is not small. The first day after the bill announcement, Indian market experienced a deep fall. Before 2018, Indian situation had direct co-relation with average International bitcoin price. But after the introduction of pegged coins like USDT, market is working in two way: Indian Rupee <--> USDT <--> bitcoin

Current price of US Dollar in Indian Rupee is Rs. 73. Now see the chart below:


(image courtesy: WazirX)

USDT price declined to Rs. 60 (-20% from international price) on 31st Jan. So, first hit was taken by pegged coin. With current Indian volume, impact on USD price of bitcoin would have started if price of USDT declined below the level of Rs. 54-56, after that USDT would have been saturated and bitcoin would have started falling in dollar value. But that didn't happen because Indians expected that Finance Minister would say something about the bill in budget speech but she didn't say anything making people believe that cryptocurrencies are just small petty item in government's list of agenda and bill most likely won't be passed. Hence, positivity once again kicked in Indian market on 1st Feb and USDT price is once again trading around Rs. 74-75 (1-2% premium).

I just wrote a post in Indian section highlighting my views on why the bill most likely won't get passed: https://bitcointalk.org/index.php?topic=5313704.msg56250260#msg56250260
20  Local / India / Re: Updates on crypto ban bill on: February 02, 2021, 01:36:16 PM
If you have any updates or something useful regarding crypto ban bill, please feel free to share it here with community.
We need to stand United on this. We have to convince Government not to ban crypto.
Let's do it.

Okay, there are couple of things that everyone should understand:

1. Content of bill isn't out yet. So, there's a possibility that government is only planning to ban the use of cryptocurrencies as tender. Trading may continue.
2. Government is planning to allow the use of certain cryptocurrencies alongside CBDC. So, we may still able to use bitcoin and other major altcoins even after ban.



Now coming to the current scenario, in my opinion, it's highly unlikely that bill will be passed in current session. Only 31 days of working left, under-staffing due to Corona, around 20 bills in line, there's very less chances that Crypto Bill would be presented in both house and get passed.

In case bill isn't get passed, two things could happen, either bill will be presented or it won't. In case, it doesn't then current unregulated market will continue and we will have more time to persuade government to go for regulation instead of ban (this industry is growing exponentially, government can't just shut it down). In case, bill gets presented in the house, government has to provide the blueprint on how current holders would dispose their wealth. Around 80-90 lakh Indians are involved in crypto (white-labelled transactions), in case of blanket ban, price in Indian market would drop to zero and we won't left with any option to sell (government wouldn't want to see such situation). So, with healthy parliamentary discussion, the bill may refer to standing committee to further think about the situation. If it does, I am expecting that the committee would call for the recommendation from industry experts and stakeholders. If that happens, we all will try our best to change the government's decision. By we, I mean the major exchanges and crypto startups in India, as far as I know, all of 'em have all already prepared the necessary report to be presented in case (I also contributed in one draft).

So, there's nothing to be panic about right now. We are matures and want direct dialogues with government unlike farmers' situation.



And guys, stop troubling USDT! Let it breathe around ₹77-80. Stop plunging it to ₹60. Cheesy
Pages: [1] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 ... 144 »
Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!