diff options
author | John Wiegley <johnw@newartisans.com> | 2023-11-24 23:33:59 -0800 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2024-08-05 08:35:56 -0700 |
commit | 67de3bce35de8158cd25750901a322cc02071c95 (patch) | |
tree | 984346a9cdd73dcd7c9dbc9175143e1f759a8263 /src/xact.cc | |
parent | 6e9fda06df1754f58c347e44a4579d059dfd36f0 (diff) | |
download | fork-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.cc | 34 |
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 { |