Auto merge of #1144 - bitcartel:zc.v0.11.2.z7_tx_malleability_gettxid, r=bitcartel
A fix for transaction malleability This PR fixes transaction malleability by not including the sigscript of transaction inputs and joinsplit sigs when hashing the txid. This PR supercedes PR #1101 which was a minimal solution based on a new serialization flag. This PR introduces GetTxid() to distinguish between getting a transaction id and the double sha256 hash. The key changes are: - Adding GetTxid() method to CTransaction which makes a copy of the transaction, clearing out the sigscript and joinsplitsig fields, before hashing. - Verifying that every call to GetHash() actually wants a txid, and replacing with GetTxid(). - Renaming GetHash() to GetSerializeHash() - Rationale: In future, upstream code we want to merge will use GetHash() but we don't know the intent. We should check to see if the intent is to receive a txid (most likely) in which case we replace with GetTxid(), or if upstream actually wants a double hash of the transaction we can use GetSerializeHash(). - Updated genesis data in chainparams.cpp Note that coinbase transactions are excluded as they need the sigscript hashed to help avoid duplicate txids per BIP34: - This modification is related to a question from @ebfull on PR #1101 - "Can we think of a way this change allows us to construct two transactions with the same txid which can simultaneously appear in the blockchain? My guess is it would be possible to construct a coinbase transaction of such a form... this surely breaks invariants." This PR Passes all tests in test_bitcoin (test data was updated in bloom_tests, miner_tests and script_tests).
This commit is contained in:
@@ -74,7 +74,7 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
|
||||
entry.push_back(Pair("blockindex", wtx.nIndex));
|
||||
entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
|
||||
}
|
||||
uint256 hash = wtx.GetHash();
|
||||
uint256 hash = wtx.GetTxid();
|
||||
entry.push_back(Pair("txid", hash.GetHex()));
|
||||
Array conflicts;
|
||||
BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
|
||||
@@ -439,7 +439,7 @@ Value sendtoaddress(const Array& params, bool fHelp)
|
||||
|
||||
SendMoney(address.Get(), nAmount, fSubtractFeeFromAmount, wtx);
|
||||
|
||||
return wtx.GetHash().GetHex();
|
||||
return wtx.GetTxid().GetHex();
|
||||
}
|
||||
|
||||
Value listaddressgroupings(const Array& params, bool fHelp)
|
||||
@@ -916,7 +916,7 @@ Value sendfrom(const Array& params, bool fHelp)
|
||||
|
||||
SendMoney(address.Get(), nAmount, false, wtx);
|
||||
|
||||
return wtx.GetHash().GetHex();
|
||||
return wtx.GetTxid().GetHex();
|
||||
}
|
||||
|
||||
|
||||
@@ -1023,7 +1023,7 @@ Value sendmany(const Array& params, bool fHelp)
|
||||
if (!pwalletMain->CommitTransaction(wtx, keyChange))
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed");
|
||||
|
||||
return wtx.GetHash().GetHex();
|
||||
return wtx.GetTxid().GetHex();
|
||||
}
|
||||
|
||||
// Defined in rpcmisc.cpp
|
||||
@@ -1135,7 +1135,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
|
||||
tallyitem& item = mapTally[address];
|
||||
item.nAmount += txout.nValue;
|
||||
item.nConf = min(item.nConf, nDepth);
|
||||
item.txids.push_back(wtx.GetHash());
|
||||
item.txids.push_back(wtx.GetTxid());
|
||||
if (mine & ISMINE_WATCH_ONLY)
|
||||
item.fIsWatchonly = true;
|
||||
}
|
||||
@@ -2324,7 +2324,7 @@ Value listunspent(const Array& params, bool fHelp)
|
||||
CAmount nValue = out.tx->vout[out.i].nValue;
|
||||
const CScript& pk = out.tx->vout[out.i].scriptPubKey;
|
||||
Object entry;
|
||||
entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
|
||||
entry.push_back(Pair("txid", out.tx->GetTxid().GetHex()));
|
||||
entry.push_back(Pair("vout", out.i));
|
||||
CTxDestination address;
|
||||
if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
|
||||
|
||||
Reference in New Issue
Block a user