Skip to content

Instantly share code, notes, and snippets.

@SurfingNerd
Created June 18, 2019 17:15
Show Gist options
  • Save SurfingNerd/2be70efd789912b5a9a51d662c38ed40 to your computer and use it in GitHub Desktop.
Save SurfingNerd/2be70efd789912b5a9a51d662c38ed40 to your computer and use it in GitHub Desktop.
Bug: Failing correct web3 extensions
/**
* @author Thomas Haller <[email protected]>
* @abstract showcases an issue creating a web3 transaction with RSV if R or S has a leading zeros
* Those leading zeros are optimized away by ethereumjs-tx but are required later by the RLP Logic.
* This code sample is designed to be easy adoptable to be picked up for an automatic test.
* it was tested with [email protected].
* Since beta.51 ethereumjs-tx is referenced by web3.
*
* @see https://github.com/ethereumjs/ethereumjs-tx/issues/140
*/
const Web3 = require('web3')
const Tx = require('ethereumjs-tx');
const web3_options = {
transactionConfirmationBlocks: 1,
defaultGasPrice: 1000000000
}
const rpcAddress = 'http://127.0.0.1:9545/';
var web3 = new Web3(rpcAddress, null, web3_options);
const txRaw = {
nonce: '0x00',
gasPrice: 1000000000,
gas: 21000,
to: '0x92d8099b5b4dd10234ec8f1f03e691aeea2f6527',
value: 1000
};
const tx = new Tx(txRaw);
const address = "0x0774fe042Bc23D01599B5A92b97B3125a4Cb20EE";
// a valid signature for this transaction:
const r = "707f45cea1c62ded74d5a7ee2e40bebc4adf79f2cffc94e73527c5903b98cddb";
const s = "00c3749242f56c7c06a842e516d43e97bd35e1127708a76277e998ea1257f6ed";
const v = "1b";
tx.r = "0x" + r;
tx.s = "0x" + s;
tx.v = "0x" + v;
var serializedTx = toHex(tx.serialize());
var recoveredAddress;
try {
recoveredAddress = web3.eth.accounts.recoverTransaction(serializedTx)
console.assert(recoveredAddress == address, "Unexpected: recovery was success, but address is wrong:" + recoveredAddress)
console.log("hoorray - recover success - bug is fixed in web3 library: " + recoveredAddress);
return;
} catch(error) {
console.log("BUG is still here: RLP is wrong.");
}
//i am fixing the problem here by manipulating the serialized RLP string.
//i replace the problematic 31 byte long string with a 32 byte string
//and taking care about the RLP values as well.
// 9f is the size header in the case the leading zero has been optimized away
// a0 is the size header in the case where the leading zero is kept.
var searchString = "9f" + s.slice(2, 64);
var replaceString = "a0" + s;
console.log("searchString:" + searchString);
console.log("replaceString:" + replaceString);
serializedTx = serializedTx.replace(searchString, replaceString);
console.log("Repaired Transaction: " + serializedTx);
//now we have repaired the transaction and can prove that it is valid
try {
recoveredAddress = web3.eth.accounts.recoverTransaction(serializedTx)
console.assert(recoveredAddress == address, "Unexpected: recovery was success, but address is wrong:" + recoveredAddress)
console.log("recover success with repeaired transaction: " + recoveredAddress);
} catch(error) {
console.error("UNEXPECTED ERROR:", error);
}
function toHex(nonHex, prefix = true) {
let temp = nonHex.toString('hex');
if (prefix) {
temp = `0x${temp}`;
}
return temp;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment