5

I am trying to implement a voting system in nodejs. My server needs to be able to create transactions and send them to the ethereum blockchain when provided with the user private key. I have tried doing so using different modules however I seem to always run into the same issue. - The connection with the RPC works fine - The transaction seems to be created just right - Transaction is registered as sent to the network by my local node but will never appear in the blokchain.

I have managed to have transactions registered while using web3 but I can't do it the same way if I want to be able to sign transactions myself. Tests were done using both a local or remote ( infura ) node on the testnet ( ropsten and kovan ). I may have a hint of the problem : - When creating a transaction (succesful) with web3 my local node sees the transaction hash as '0x456515...' and the address as '0xcfnsk55sghHG...' - When doing the same with ethereumjs-tx to sign the transaction, the node sees it as '456515...' and '&cfnsk55sghHG...' I am looking for any information / help as to what the problem is or how to solve it =)

var Web3 = require('web3');
var Tx = require('ethereumjs-tx');
var _ = require('lodash');
var SolidityFunction = require('web3/lib/web3/function');
var keythereum = require("keythereum");
var web3 = new Web3();

web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545"));

var toAccount ='0x2824dD13D388ed0Df7Ae1b5697b7b66E737E021a';
var fromAccount = '0x4129c6A02caB77DeEdBDC221904a3dc1ab7cAAfE';
var privateKey = Buffer.from('My Private Key', 'hex' );
gasPrice = web3.eth.gasPrice;
gasPriceHex = web3.toHex(gasPrice);
gasLimitHex = web3.toHex(300000);
console.log('Current gasPrice: ' + gasPrice + ' OR ' + gasPriceHex);
nonce =  web3.eth.getTransactionCount(fromAccount) ;
nonceHex = web3.toHex(nonce);
console.log('nonce (transaction count on fromAccount): ' + nonce + '(' + nonceHex + ')');

var rawTx = {
    nonce: '0x85555',
    gasPrice: gasPriceHex,
    gasLimit: gasLimitHex,
    to: toAccount,
    from: fromAccount,
    value: web3.toHex(web3.toWei ( 1, "ether")),
    data: '0x7f7465737435000',
    chainId: '0x3',
};

var tx = new Tx(rawTx);
tx.sign(privateKey);
var serializedTx = tx.serialize();

web3.eth.sendRawTransaction('0x'+serializedTx.toString('hex'), function (err, hash) {
    if (err) {
        console.log('Error:');
        console.log(err);
    }
    else {
        console.log('Transaction receipt hash pending');
        console.log(hash);
    }
});

Thank You

-

  • hey, I've been trying to do the same thing today. I somehow managed to succesfully send two raw transactions and then it suddenly stopped working for an unknown reason. Try to broadcast your serializedTx from here testnet.etherscan.io/pushTx` and post here what you get . I get {"jsonrpc":"2.0","result":"0xe007db86af6ec68de1d1e4cdce8d027978cc5db541e134134fa706f51e4af34e","id":1} and transaction never shows up on the blockchain. And please post an answer if you find a solution. Good luck, friend! – manidos Mar 6 '17 at 12:22
  • I got {"jsonrpc":"2.0","result":"0x13cd8bbbb6014a39657987a5bdb9973b09a12881749bc21e4dd5337dd2bf9a72","id":1} with a greenlight. The problem is when I lookup this particular transaction it seems to keep the 'pending' status for ever. – Alex Triquet Mar 6 '17 at 13:08
  • check out this issue, github.com/ethereumjs/ethereumjs-tx/issues/51. It seems that that the problem might be related to Buffer class and how it encodes hex or something like that. – manidos Mar 6 '17 at 13:25
  • Well, seems like we are stuck waiting for next patch, unless we find a homemade work around – Alex Triquet Mar 6 '17 at 13:31
  • I am not sure that this is the real issue here though because it would cause the sending operation to fail, preventing us from getting a TxId, which is not the case here. – Alex Triquet Mar 6 '17 at 14:15
4

I don't know if that's a proper way of sending a raw transaction, but it works. Just tested it.

const Web3 = require('web3');
const Tx = require('ethereumjs-tx');
const config = require('./config');

const web3 = new Web3(new Web3.providers.HttpProvider(config.provider)); //link provided by Infura.io
web3.eth.defaultAccount = "0xc929c890f1398d5c1ecdf4f9ecec016906ac9f7f";

const getNonce = () => {
  return new Promise((resolve, reject) => {
    web3.eth.getTransactionCount(web3.eth.defaultAccount, (error, result) => {
      if(error) reject(error);
      resolve(web3.toHex(result));
    })
  })
}
const getGasPrice = () => {
  return new Promise((resolve, reject) => {
    web3.eth.getGasPrice((error, result) => {
      if(error) reject(error);
      resolve(web3.toHex(result.toNumber()));
    })
  })
}

const sendRawTransaction = (rawTx) => {
  const privateKey = "190b820c2627f26fd1b973b72dcba78ff677ca4395c64a4a2d0f4ef8de36883c";
  const tx = new Tx(rawTx);
  const privateKeyBuffer = Buffer.from(privateKey, 'hex');
  tx.sign(privateKeyBuffer);
  const serializedTx = tx.serialize();
  web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), function(err, hash) {
      console.log('Error:', err);
      console.log('Hash:', hash);
  });
}

Promise.all([getNonce(), getGasPrice()])
  .then(values => {
    const rawTx = {
      to: '0x203D17B4a1725E001426b7Ab3193E6657b0dBcc6',
      gasLimit: web3.toHex(1000000),
      value: web3.toHex(web3.toWei('0.1', 'ether')),
      nonce: values[0],
      gasPrice: values[1]
    };
    console.log(rawTx);
    return(rawTx);
  })
  .then(sendRawTransaction)
  .catch(e => console.log(e))

console:

{ 
  to: '0x203D17B4a1725E001426b7Ab3193E6657b0dBcc6',
  gasLimit: '0xf4240',
  value: '0x16345785d8a0000',
  nonce: '0x5',
  gasPrice: '0x4a817c800' 
}
Error: null
Hash: 0x2a156efdaa6be587544f32cdf7bac140bbee20dafda2c561a4c9195c6fa6729c

Here's how I generated key pair and address:

const keythereum = require('keythereum');
const utils = require('ethereumjs-util');

const params = {keyBytes: 32, ivBytes: 16};
const dk = keythereum.create(params);
const private = utils.bufferToHex(dk.privateKey);
const public = utils.bufferToHex(utils.privateToPublic(dk.privateKey));
const address = utils.bufferToHex(utils.privateToAddress(dk.privateKey));
  • how can I achieve it using json rpc + curl – Yogesh Karodiya Nov 6 '17 at 13:42
3

Well, I have finally found the answer to all of those problems, as was stated before the nonce was at fault here, except it is kind subtle. Every transaction you send with an account you are supposed to increase a nonce which is tied to the account. The best way to do it is to use :

nonce = web3.eth.getTransactionCount(fromAccount);

However on the testnet (ropsten, not kovan) the Initial Account Nonce is set to 0x100000 so you have to use :

nonce = web3.eth.getTransactionCount(fromAccount) + 1048576;

The address appearing in the client (geth, parity,...) as "&28..." or "0x28..." makes no difference. Be Very careful about using consecutive nonces.

1

quick observation:

  • rawTx.from isn't a valid field and will be ignored. tx.from is a read-only field that is computed from tx.r and tx.s, which represent the signature that is produced when tx.raw is signed with a privateKey

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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