Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
Add test txhash collision Bump ethereumjs-tx vers (#196)
Browse files Browse the repository at this point in the history
Resolves #547
  • Loading branch information
nicholasjpaterno authored and davidmurdoch committed Nov 7, 2018
1 parent 5edd2a8 commit 7f837ab
Show file tree
Hide file tree
Showing 12 changed files with 520 additions and 1,225 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ node_js:
- "lts/carbon"
- "lts/*"


addons:
apt:
sources:
Expand Down
12 changes: 5 additions & 7 deletions lib/blockchain_double.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,7 @@ BlockchainDouble.prototype.putBlock = function(block, logs, receipts, callback)
];

block.transactions.forEach(function(tx, index) {
var txHash = to.hex(tx.hash());

var txHash = to.txHash(tx);
requests.push(
self.database.transactions.set.bind(
self.database.transactions,
Expand Down Expand Up @@ -303,7 +302,7 @@ BlockchainDouble.prototype.popBlock = function(callback) {
var blockHash = to.hex(block.hash());

block.transactions.forEach(function(tx) {
var txHash = to.hex(tx.hash());
var txHash = to.txHash(tx);

requests.push(
self.database.transactions.del.bind(
Expand Down Expand Up @@ -651,7 +650,7 @@ BlockchainDouble.prototype.processBlock = function(block, commit, vm, callback)
var result = results.results[v];
var receipt = results.receipts[v];
var tx = block.transactions[v];
var txHash = tx.hash();
var txHash = to.txHash(tx, true);
var txLogs = [];

// Only process the transaction's logs if it didn't error.
Expand Down Expand Up @@ -897,8 +896,7 @@ BlockchainDouble.prototype.processTransactionTrace = function(hash, params, call

function beforeTxListener(tx) {
txCurrentlyProcessing = tx;
txHashCurrentlyProcessing = to.hex(tx.hash());

txHashCurrentlyProcessing = to.txHash(tx);
if (txHashCurrentlyProcessing === targetHash) {
vm.on("step", stepListener);
}
Expand Down Expand Up @@ -949,7 +947,7 @@ BlockchainDouble.prototype.processTransactionTrace = function(hash, params, call
block.transactions.push(tx);

// After including the target transaction, that's all we need to do.
if (to.hex(tx.hash()) === targetHash) {
if (to.txHash(tx) === targetHash) {
break;
}
}
Expand Down
11 changes: 8 additions & 3 deletions lib/database/txserializer.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
var to = require("../utils/to");
var utils = require("ethereumjs-util");
var FakeTransaction = require("ethereumjs-tx/fake.js");
var Transaction = require("ethereumjs-tx");

module.exports = {
encode: function(tx, done) {
var encoded = tx.toJSON(true);

encoded.from = to.hex(tx.from);
encoded.hash = to.hex(tx.hash());
encoded.hash = to.txHash(tx);

encoded._isRawTx = tx._isRawTx;

done(null, encoded);
},
Expand All @@ -16,7 +19,7 @@ module.exports = {
// JSON serialization types: ethereumjs-tx, and web3.
// Here we deserialize from ethereumjs-tx because it's
// closer to the metal, so to speak.
var tx = new FakeTransaction({
const options = {
nonce: utils.toBuffer(json.nonce),
value: utils.toBuffer(json.value),
to: utils.toBuffer(json.to),
Expand All @@ -27,7 +30,9 @@ module.exports = {
v: utils.toBuffer(json.v),
r: utils.toBuffer(json.r),
s: utils.toBuffer(json.s)
});
};

let tx = json._isRawTx ? new Transaction(options) : new FakeTransaction(options);

// if (to.hex(tx.hash()) != json.hash) {
// return done(new Error("DB consistency check: Decoded transaction hash didn't match encoded hash.
Expand Down
26 changes: 17 additions & 9 deletions lib/statemanager.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var Account = require("ethereumjs-account");
var RuntimeError = require("./utils/runtimeerror");
var FakeTransaction = require("ethereumjs-tx/fake.js");
var Transaction = require("ethereumjs-tx");
var utils = require("ethereumjs-util");
var seedrandom = require("seedrandom");
var bip39 = require("bip39");
Expand Down Expand Up @@ -255,7 +256,7 @@ StateManager.prototype.getCode = function(address, number, callback) {
StateManager.prototype.queueRawTransaction = function(rawTx, callback) {
var data = Buffer.from(utils.stripHexPrefix(rawTx), "hex");

var tx = new FakeTransaction(data);
var tx = new Transaction(data);
var txParams = {
from: tx.from.toString("hex"),
to: tx.to.toString("hex"),
Expand Down Expand Up @@ -366,7 +367,7 @@ StateManager.prototype.queueTransaction = function(method, txParams, blockNumber
var self = this;
var address = utils.toBuffer(txParams.from);

// we don't call createFakeTransactionWithCorrectNonce here because then we'd need to worry
// we don't call createTransactionWithCorrectNonce here because then we'd need to worry
// about nonce calculation for the items pending in the action_queue.
// Instead, we simply create a `FakeTransaction` and bail on validation
// errors so that we fail fast when we have bad tx input
Expand Down Expand Up @@ -555,7 +556,7 @@ StateManager.prototype.processBlock = function(timestamp, callback) {
async.eachSeries(
transactions,
function(tx, finishedPrinting) {
var hash = to.hex(tx.hash());
var hash = to.txHash(tx);
var error = runtimeError == null ? { results: {} } : runtimeError;
self.printTransactionReceipt(hash, error.results[hash], finishedPrinting);
},
Expand Down Expand Up @@ -621,7 +622,7 @@ StateManager.prototype.processBlocks = function(totalBlocks, callback) {
StateManager.prototype.processCall = function(from, rawTx, blockNumber, callback) {
var self = this;

self.createFakeTransactionWithCorrectNonce(rawTx, from, function(err, tx) {
self.createTransactionWithCorrectNonce(rawTx, from, function(err, tx) {
if (err) {
return callback(err);
}
Expand Down Expand Up @@ -650,7 +651,7 @@ StateManager.prototype.processCall = function(from, rawTx, blockNumber, callback
StateManager.prototype.processGasEstimate = function(from, rawTx, blockNumber, callback) {
var self = this;

self.createFakeTransactionWithCorrectNonce(rawTx, from, function(err, tx) {
self.createTransactionWithCorrectNonce(rawTx, from, function(err, tx) {
if (err) {
return callback(err);
}
Expand All @@ -673,14 +674,14 @@ StateManager.prototype.processGasEstimate = function(from, rawTx, blockNumber, c
StateManager.prototype.processTransaction = function(from, rawTx, callback) {
var self = this;

self.createFakeTransactionWithCorrectNonce(rawTx, from, function(err, tx) {
self.createTransactionWithCorrectNonce(rawTx, from, function(err, tx) {
if (err) {
return callback(err);
}

self.blockchain.queueTransaction(tx);

var txHash = to.hex(tx.hash());
var txHash = to.txHash(tx);

// If we're not currently mining or we're mining on an interval,
// only queue the transaction, don't process it.
Expand Down Expand Up @@ -907,14 +908,21 @@ StateManager.prototype.isUnlocked = function(address) {
return this.unlocked_accounts[address.toLowerCase()] != null;
};

StateManager.prototype.createFakeTransactionWithCorrectNonce = function(rawTx, from, callback) {
StateManager.prototype.createTransactionWithCorrectNonce = function(rawTx, from, callback) {
const self = this;
self.blockchain.getQueuedNonce(from, (err, expectedNonce) => {
if (err) {
return callback(err);
}

var tx = new FakeTransaction(rawTx);
var tx;
if (rawTx.hasOwnProperty("v") && rawTx.hasOwnProperty("r") && rawTx.hasOwnProperty("s")) {
tx = new Transaction(rawTx);
tx._isRawTx = true;
} else {
tx = new FakeTransaction(rawTx);
tx._isRawTx = false;
}
tx.from = from;

// If the user specified a nonce, use that instead.
Expand Down
2 changes: 1 addition & 1 deletion lib/utils/block_helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ module.exports = {
if (includeFullTransactions) {
return txhelper.toJSON(tx, block);
} else {
return to.hex(tx.hash());
return to.txHash(tx);
}
}),
uncles: [] // block.uncleHeaders.map(function(uncleHash) {return to.hex(uncleHash)})
Expand Down
8 changes: 6 additions & 2 deletions lib/utils/receipt.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var to = require("./to");
var Transaction = require("ethereumjs-tx");

function Receipt(tx, block, logs, gasUsed, cumulativeGasUsed, contractAddress, status, logsBloom) {
this.tx = tx;
Expand All @@ -12,9 +13,12 @@ function Receipt(tx, block, logs, gasUsed, cumulativeGasUsed, contractAddress, s

this.transactionIndex = 0;

let inclSig = !(tx instanceof Transaction);
this.txHash = tx.hash(inclSig);

for (var i = 0; i < block.transactions.length; i++) {
var current = block.transactions[i];
if (current.hash().equals(tx.hash())) {
if (current.hash(inclSig).equals(this.txHash)) {
this.transactionIndex = i;
break;
}
Expand All @@ -24,7 +28,7 @@ function Receipt(tx, block, logs, gasUsed, cumulativeGasUsed, contractAddress, s
Receipt.prototype.toJSON = function() {
// Enforce Hex formatting as defined in the RPC spec.
return {
transactionHash: to.rpcDataHexString(this.tx.hash()),
transactionHash: to.rpcDataHexString(this.txHash),
transactionIndex: to.rpcQuantityHexString(this.transactionIndex),
blockHash: to.rpcDataHexString(this.block.hash()),
blockNumber: to.rpcQuantityHexString(this.block.header.number),
Expand Down
3 changes: 1 addition & 2 deletions lib/utils/runtimeerror.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ RuntimeError.prototype.combine = function(transactions, vmOutput) {

// 1 means no error, oddly.
if (result.vm.exception !== 1) {
var hash = to.hex(tx.hash());

var hash = to.txHash(tx);
this.hashes.push(hash);
var reason;
var returnData = result.vm.return;
Expand Down
21 changes: 20 additions & 1 deletion lib/utils/to.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var utils = require("ethereumjs-util");
let utils = require("ethereumjs-util");
let Transaction = require("ethereumjs-tx");

module.exports = {
// Note: Do not use to.hex() when you really mean utils.addHexPrefix().
Expand Down Expand Up @@ -28,6 +29,24 @@ module.exports = {
return utils.addHexPrefix(val);
},

txHash: function(tx, getBuffer = false) {
let txHash;

if (typeof tx.hash === "function") {
// If signed transaction dont use signature for hash
// For FakeTransaction/Transaction compatibility
if (tx instanceof Transaction) {
txHash = tx.hash(false);
} else {
txHash = tx.hash();
}
} else {
txHash = Buffer.alloc(0);
}

return getBuffer ? txHash : utils.addHexPrefix(txHash.toString("hex"));
},

rpcQuantityHexString: function(val) {
val = this.hex(val);
val = "0x" + val.replace("0x", "").replace(/^0+/, "");
Expand Down
2 changes: 1 addition & 1 deletion lib/utils/txhelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module.exports = {
}
}
var resultJSON = {
hash: to.nullableRpcDataHexString(tx.hash()),
hash: to.nullableRpcDataHexString(to.txHash(tx)),
nonce: to.rpcQuantityHexString(tx.nonce),
blockHash: to.nullableRpcDataHexString(block.hash()),
blockNumber: to.rpcQuantityHexString(block.header.number),
Expand Down
Loading

0 comments on commit 7f837ab

Please sign in to comment.