[Ethereum] Extended private key vs private key

hd-walletsprivate-keypublic-keytransactions

I am trying to make an hd wallet based on nodejs. So to have a secure wallet I have created wallet in my offline machine

const hdkey = require('ethereumjs-wallet/hdkey');
const bip39 = require('bip39');
var seed = bip39.mnemonicToSeed('my_mnemonic', 'my_password');
var chain = hdkey.fromMasterSeed(seed);
var xpub = chain.publicExtendedKey();
var xpriv = chain.privateExtendedKey();

Than using xpub I am generating addresses for users.

const wallet = require('ethereumjs-wallet');
const hdkey = require('ethereumjs-wallet/hdkey');
const _____ = require('dotenv').config();

const generate = async (index) => {

    const xpub = process.env.ETH_XPUB;

    const hdk = hdkey.fromExtendedKey(xpub);

    index = index || 0;

    const child = hdk.deriveChild(index);
    const w = wallet.fromExtendedPublicKey(child.publicExtendedKey());

    return w.getAddressString();
};
generate().then(v => {
    console.log(v);
}).catch(error => {
    console.log(error);
});

Ok, now I want to send coins from these addreses to my own address using extended private key – xpriv

const ethTx = require('ethereumjs-tx');
const Web3 = require('web3');


const web3 = new Web3(
    new Web3.providers.HttpProvider('http://localhost:8545')
);

//Verify connection is successful
web3.eth.net.isListening()
    .then(() => console.log('is connected'))
    .catch(e => console.log('Wow. Something went wrong'));


const params = {
    nonce: 0,
    to: '0x4584158529818ef77D1142bEeb0b6648BD8eDb2f',
    value: '0.1',
    gasPrice: 5000000000,
    gasLimit: 21000,
    chainId: 3
};
const privKey = new Buffer('xprv9s21ZrQH143K36eJpjZxNPYbNjzzUMvqLSG6P6Sex1unL8meREsNkcMNRw4ntv3WjJ2tJJX3CrdxkCJdyo7zLnjqdFppov2BAvY4iXYuMCY','base64');
const tx = new ethTx(params);

//Signing the transaction with the correct private key
tx.sign(privKey); //ERROR HERE


const serializedTx = tx.serialize();
Web3.eth.sendSignedTransaction(
    `0x${serializedTx.toString('hex')}`,
    (error, result) => {
        if (error) { console.log(`Error: ${error}`); }
        else { console.log(`Result: ${result}`); }
    }
);

When trying to sign I am getting an error that the private key is invalid. Waht private key I need to use to sign transactions.

Best Answer

You don't sign the transaction with the Master Private Key. You sign it with the private key that corresponds to the sender's address:

const hdkey = require('ethereumjs-wallet/hdkey');
const bip39 = require('bip39');
var seed = bip39.mnemonicToSeed('my_mnemonic', 'my_password');
var chain = hdkey.fromMasterSeed(seed);
var addr_node = chain.derivePath(senders_derivation_path);
//if addr is the same with the address you want to send from, then its corresponding private_key will also be valid. Otherwise, most probably the senders_derivation_path is wrong
var addr = addr_node.getWallet().getAddressString();
var private_key = addr_node.getWallet().getPrivateKey();
Related Topic