summaryrefslogtreecommitdiff
path: root/src/xact.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2023-11-24 23:33:59 -0800
committerJohn Wiegley <johnw@newartisans.com>2024-08-05 08:35:56 -0700
commit67de3bce35de8158cd25750901a322cc02071c95 (patch)
tree984346a9cdd73dcd7c9dbc9175143e1f759a8263 /src/xact.cc
parent6e9fda06df1754f58c347e44a4579d059dfd36f0 (diff)
downloadfork-ledger-67de3bce35de8158cd25750901a322cc02071c95.tar.gz
fork-ledger-67de3bce35de8158cd25750901a322cc02071c95.tar.bz2
fork-ledger-67de3bce35de8158cd25750901a322cc02071c95.zip
Make xact hashes independent of posting order
Also, support matching provided hashes against a prefixed of the generated hash.
Diffstat (limited to 'src/xact.cc')
-rw-r--r--src/xact.cc34
1 files changed, 31 insertions, 3 deletions
diff --git a/src/xact.cc b/src/xact.cc
index 0b9bd9cd..5c3c7042 100644
--- a/src/xact.cc
+++ b/src/xact.cc
@@ -581,6 +581,19 @@ bool xact_t::valid() const
return true;
}
+extern "C" unsigned char *SHA512(
+ void *data, unsigned int data_len, unsigned char *digest);
+
+namespace {
+ std::string bufferToHex(const unsigned char* buffer, std::size_t size) {
+ std::ostringstream oss;
+ oss << std::hex << std::setfill('0');
+ for(std::size_t i = 0; i < size; ++i)
+ oss << std::setw(2) << static_cast<int>(buffer[i]);
+ return oss.str();
+ }
+}
+
string xact_t::hash(string nonce) const {
std::ostringstream repr;
repr << nonce;
@@ -588,12 +601,27 @@ string xact_t::hash(string nonce) const {
repr << aux_date();
repr << code;
repr << payee;
- string hash(repr.str());
posts_list all_posts(posts.begin(), posts.end());
+ std::vector<std::string> strings;
foreach (post_t * post, all_posts) {
- hash = post->hash(hash);
+ std::ostringstream posting;
+ posting << post->account->fullname();
+ if (! post->amount.is_null())
+ posting << post->amount.to_fullstring();
+ if (post->cost)
+ posting << post->cost->to_fullstring();
+ posting << post->checkin;
+ posting << post->checkout;
+ strings.push_back(posting.str());
+ }
+ std::sort(strings.begin(), strings.end());
+ foreach (string& str, strings) {
+ repr << str;
}
- return hash;
+ unsigned char data[128];
+ string repr_str(repr.str());
+ SHA512((void *)repr_str.c_str(), repr_str.length(), data);
+ return bufferToHex(data, 64 /*SHA512_DIGEST_LENGTH*/);
}
namespace {