Please describe what you are doing to trigger the bug:
I am trying to check
(and list
revisions of) the same storage (& id) from two different hosts : one AMD64 architecture and one ARM64 architecture (MacBook Pro M1). The storage is encrypted and is using erasure-coding (5/2). I have compiled latest Duplicacy on both hosts (from commit Bump version to 3.0.1 · gilbertchen/duplicacy@72eb339 · GitHub).
The command I run :
duplicacy -d -v list -id SNAPSHOT_ID
Please describe what you expect to happen (but doesn’t):
Both hosts should show the same result since they have the same config for the remote storage. Either the remote storage has complete shards, or it has incomplete shards.
Please describe what actually happens (the wrong behaviour):
- Host on AMD64 machine shows the list of revisions with no issue.
- Host on ARM64 machine shows an issue regarding incomplete shards :
Failed to decrypt the file snapshots/SNAPSHOT_ID/1: Not enough chunk data for recover; only 0 out of 7 shards are complete
I made sure that…
- I tried this with latest official release but also by compiling the same commit on both machines
- I made sure to delete the
.duplicacy/cache
on both machine before running the same command
What I have investigated so far
I tried to troubleshoot the issue by logging some intermediate values and found out something interesting. When decrypting the snaphot file on the ARM64 machine, duplicacy is comparing the hash of the shard it reads with the hash present in the snapshot file and the comparison shows the hashes are different. This sets a flag to recover the shard with the parity shards but it fails to recover since this issue occurs for all 7 shards, hence this issue. On the AMD64 machine, the comparison of the same shard shows the hashes are the same (and therefore does not require recovery).
Here is the debug info of Duplicacy trying to decrypt the same snapshot file from the two machines. I am simply logging all info I can from the shards loop located at line 429 in duplicacy/duplicacy_chunk.go at master · gilbertchen/duplicacy · GitHub . I only show the first 3 shards but results are similar for the rest :
On AMD64 machine:
**(shard 0) Bytes to be hashed : 6475706c6963616379009afb19fdc44d5320de41f18d733fb297e6cc81e3d64d763e7ebf2731d4b1c78656d3898ce105547aea7cfc4833cc2ac8e01be53106d7add0878fe8b61259d4cffdad8e7be869fc935d2f7a6a9ccedafeb3783df90db38b4242261dd57c2651d158bf8b15
**(shard 0) Hash from hasher : 7be84de55e1bab35efe9c7ade78a5d564d2f0ffed9894bbb9873fe4da827538e
**(shard 0) Hash from encryptedBuffer : 7be84de55e1bab35efe9c7ade78a5d564d2f0ffed9894bbb9873fe4da827538e
**(shard 0) Hasher key fed : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 0) Hasher (digest) key : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 0) Hasher (digest) buffer : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 0) Hasher (digest) offset : 0
**(shard 0) Hasher (digest) size : 32
**(shard 0) Hasher (digest) state : [%!!(MISSING)s(uint64=15845587454020865583) %!!(MISSING)s(uint64=11820040416388919760) %!!(MISSING)s(uint64=1376283091369227076) %!!(MISSING)s(uint64=2611923443488327891) %!!(MISSING)s(uint64=4310963063287117203) %!!(MISSING)s(uint64=138837371876027623
80) %!!(MISSING)s(uint64=13714699805381954668) %!!(MISSING)s(uint64=4983270260364809079) %!!(MISSING)s(uint64=15845587454020865583) %!!(MISSING)s(uint64=11820040416388919760) %!!(MISSING)s(uint64=1376283091369227076) %!!(MISSING)s(uint64=2611923443488327891) %!!(MISSING)s(uint64=431096306328
7117203) %!!(MISSING)s(uint64=13883737187602762380) %!!(MISSING)s(uint64=13714699805381954668) %!!(MISSING)s(uint64=4983270260364809079)]
**(shard 0) Hasher Size : 32
**(shard 0) Hasher BlockSize : 32
**(shard 0) Hasher - # bytes written : 110
**(shard 1) Bytes to be hashed : e860c707f02c9e8ca6f1ee1de5951eccdb8cc97568afb90f49ee5f694c3adc9b858e578e1030fe4cfd8b3a3b6812258a3b6a64a9f856e7da03172578772887f0b8e477ed3fd5168a85a94c568cf49c04e9ff2a3d28bae035ef53ab5b92bd198faefea24c3d0e202f5cb29a63f4aa
**(shard 1) Hash from hasher : 01816459adac99bc871119f8cd1e13d1f5623fbc1c9a2cacfa315f187ba68c31
**(shard 1) Hash from encryptedBuffer : 01816459adac99bc871119f8cd1e13d1f5623fbc1c9a2cacfa315f187ba68c31
**(shard 1) Hasher key fed : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 1) Hasher (digest) key : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 1) Hasher (digest) buffer : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 1) Hasher (digest) offset : 0
**(shard 1) Hasher (digest) size : 32
**(shard 1) Hasher (digest) state : [%!!(MISSING)s(uint64=15845587454020865583) %!!(MISSING)s(uint64=11820040416388919760) %!!(MISSING)s(uint64=1376283091369227076) %!!(MISSING)s(uint64=2611923443488327891) %!!(MISSING)s(uint64=4310963063287117203) %!!(MISSING)s(uint64=138837371876027623
80) %!!(MISSING)s(uint64=13714699805381954668) %!!(MISSING)s(uint64=4983270260364809079) %!!(MISSING)s(uint64=15845587454020865583) %!!(MISSING)s(uint64=11820040416388919760) %!!(MISSING)s(uint64=1376283091369227076) %!!(MISSING)s(uint64=2611923443488327891) %!!(MISSING)s(uint64=431096306328
7117203) %!!(MISSING)s(uint64=13883737187602762380) %!!(MISSING)s(uint64=13714699805381954668) %!!(MISSING)s(uint64=4983270260364809079)]
**(shard 1) Hasher Size : 32
**(shard 1) Hasher BlockSize : 32
**(shard 1) Hasher - # bytes written : 110
**(shard 2) Bytes to be hashed : 7363cf084a0e39ccf3d6ddafd1b3fc5f625a160359851462f19bf6b05d3e80308f30a97b0ace62f5497e50af6807748af121d1f5d02f51c8ab010632dc3a824aca5cd358ae4bcbdae8f84e8d1a94203da95d6b173385058c9dd655cea85c3bd260c5742e52c2355c8f9ca718c655
**(shard 2) Hash from hasher : 763ebc8429ada35bd2d56284666e5298a887a4081214a2aec503e9fa1410a94b
**(shard 2) Hash from encryptedBuffer : 763ebc8429ada35bd2d56284666e5298a887a4081214a2aec503e9fa1410a94b
**(shard 2) Hasher key fed : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 2) Hasher (digest) key : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 2) Hasher (digest) buffer : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 2) Hasher (digest) offset : 0
**(shard 2) Hasher (digest) size : 32
**(shard 2) Hasher (digest) state : [%!!(MISSING)s(uint64=15845587454020865583) %!!(MISSING)s(uint64=11820040416388919760) %!!(MISSING)s(uint64=1376283091369227076) %!!(MISSING)s(uint64=2611923443488327891) %!!(MISSING)s(uint64=4310963063287117203) %!!(MISSING)s(uint64=138837371876027623
80) %!!(MISSING)s(uint64=13714699805381954668) %!!(MISSING)s(uint64=4983270260364809079) %!!(MISSING)s(uint64=15845587454020865583) %!!(MISSING)s(uint64=11820040416388919760) %!!(MISSING)s(uint64=1376283091369227076) %!!(MISSING)s(uint64=2611923443488327891) %!!(MISSING)s(uint64=431096306328
7117203) %!!(MISSING)s(uint64=13883737187602762380) %!!(MISSING)s(uint64=13714699805381954668) %!!(MISSING)s(uint64=4983270260364809079)]
**(shard 2) Hasher Size : 32
**(shard 2) Hasher BlockSize : 32
**(shard 2) Hasher - # bytes written : 110
On ARM64 machine:
**(shard 0) Bytes to be hashed : 6475706c6963616379009afb19fdc44d5320de41f18d733fb297e6cc81e3d64d763e7ebf2731d4b1c78656d3898ce105547aea7cfc4833cc2ac8e01be53106d7add0878fe8b61259d4cffdad8e7be869fc935d2f7a6a9ccedafeb3783df90db38b4242261dd57c2651d158bf8b15
**(shard 0) Hash from hasher : 32ba19ccd3d4003537a18bc66c2710f9d80a50dda9fc608189333db8eb170450
**(shard 0) Hash from encryptedBuffer : 7be84de55e1bab35efe9c7ade78a5d564d2f0ffed9894bbb9873fe4da827538e
**(shard 0) Hasher key fed : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 0) Hasher (digest) key : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 0) Hasher (digest) buffer : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 0) Hasher (digest) offset : 0
**(shard 0) Hasher (digest) size : 32
**(shard 0) Hasher (digest) state : [%!!(MISSING)s(uint64=15845587454020865583) %!!(MISSING)s(uint64=11820040416388919760) %!!(MISSING)s(uint64=1376283091369227076) %!!(MISSING)s(uint64=2611923443488327891) %!!(MISSING)s(uint64=4310963063287117203) %!!(MISSING)s(uint64=13883737187602762380) %!!(MISSING)s(uint64=13714699805381954668) %!!(MISSING)s(uint64=4983270260364809079) %!!(MISSING)s(uint64=15845587454020865583) %!!(MISSING)s(uint64=11820040416388919760) %!!(MISSING)s(uint64=1376283091369227076) %!!(MISSING)s(uint64=2611923443488327891) %!!(MISSING)s(uint64=4310963063287117203) %!!(MISSING)s(uint64=13883737187602762380) %!!(MISSING)s(uint64=13714699805381954668) %!!(MISSING)s(uint64=4983270260364809079)]
**(shard 0) Hasher Size : 32
**(shard 0) Hasher BlockSize : 32
**(shard 0) Hasher - # bytes written : 110
**(shard 1) Bytes to be hashed : e860c707f02c9e8ca6f1ee1de5951eccdb8cc97568afb90f49ee5f694c3adc9b858e578e1030fe4cfd8b3a3b6812258a3b6a64a9f856e7da03172578772887f0b8e477ed3fd5168a85a94c568cf49c04e9ff2a3d28bae035ef53ab5b92bd198faefea24c3d0e202f5cb29a63f4aa
**(shard 1) Hash from hasher : c01fabd1ee43d4a9233527967706b885ac65ad1e8e3fc6c0772631c6fd74b1e3
**(shard 1) Hash from encryptedBuffer : 01816459adac99bc871119f8cd1e13d1f5623fbc1c9a2cacfa315f187ba68c31
**(shard 1) Hasher key fed : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 1) Hasher (digest) key : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 1) Hasher (digest) buffer : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 1) Hasher (digest) offset : 0
**(shard 1) Hasher (digest) size : 32
**(shard 1) Hasher (digest) state : [%!!(MISSING)s(uint64=15845587454020865583) %!!(MISSING)s(uint64=11820040416388919760) %!!(MISSING)s(uint64=1376283091369227076) %!!(MISSING)s(uint64=2611923443488327891) %!!(MISSING)s(uint64=4310963063287117203) %!!(MISSING)s(uint64=13883737187602762380) %!!(MISSING)s(uint64=13714699805381954668) %!!(MISSING)s(uint64=4983270260364809079) %!!(MISSING)s(uint64=15845587454020865583) %!!(MISSING)s(uint64=11820040416388919760) %!!(MISSING)s(uint64=1376283091369227076) %!!(MISSING)s(uint64=2611923443488327891) %!!(MISSING)s(uint64=4310963063287117203) %!!(MISSING)s(uint64=13883737187602762380) %!!(MISSING)s(uint64=13714699805381954668) %!!(MISSING)s(uint64=4983270260364809079)]
**(shard 1) Hasher Size : 32
**(shard 1) Hasher BlockSize : 32
**(shard 1) Hasher - # bytes written : 110
**(shard 2) Bytes to be hashed : 7363cf084a0e39ccf3d6ddafd1b3fc5f625a160359851462f19bf6b05d3e80308f30a97b0ace62f5497e50af6807748af121d1f5d02f51c8ab010632dc3a824aca5cd358ae4bcbdae8f84e8d1a94203da95d6b173385058c9dd655cea85c3bd260c5742e52c2355c8f9ca718c655
**(shard 2) Hash from hasher : 060985077815ed9f8b9b9292d4ae64ad4cb6c82fb750c59740cc797296d5494b
**(shard 2) Hash from encryptedBuffer : 763ebc8429ada35bd2d56284666e5298a887a4081214a2aec503e9fa1410a94b
**(shard 2) Hasher key fed : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 2) Hasher (digest) key : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 2) Hasher (digest) buffer : 0000000000000000000000000000000000000000000000000000000000000000
**(shard 2) Hasher (digest) offset : 0
**(shard 2) Hasher (digest) size : 32
**(shard 2) Hasher (digest) state : [%!!(MISSING)s(uint64=15845587454020865583) %!!(MISSING)s(uint64=11820040416388919760) %!!(MISSING)s(uint64=1376283091369227076) %!!(MISSING)s(uint64=2611923443488327891) %!!(MISSING)s(uint64=4310963063287117203) %!!(MISSING)s(uint64=13883737187602762380) %!!(MISSING)s(uint64=13714699805381954668) %!!(MISSING)s(uint64=4983270260364809079) %!!(MISSING)s(uint64=15845587454020865583) %!!(MISSING)s(uint64=11820040416388919760) %!!(MISSING)s(uint64=1376283091369227076) %!!(MISSING)s(uint64=2611923443488327891) %!!(MISSING)s(uint64=4310963063287117203) %!!(MISSING)s(uint64=13883737187602762380) %!!(MISSING)s(uint64=13714699805381954668) %!!(MISSING)s(uint64=4983270260364809079)]
**(shard 2) Hasher Size : 32
**(shard 2) Hasher BlockSize : 32
**(shard 2) Hasher - # bytes written : 110
My conclusion so far
The hasher does read the same shard data on both machines, but the hasher on the ARM64 machine returns a different hash for the same read bytes. I have not found what is causing the issue but I am suspecting it is related to the highwayhash
module and the implementation of either the “Sum()” or “Write()” method (my guess is more the Sum(), because ‘Hasher (digest) state’ info in debug above is identical on both machine and is read after the Write() operation). I am also not saying that the issue is coming from the fact the hosts have different architectures, it may just be a coincidence.
I am also willing to help further if needed.