From 36278166e534fe6ae9420501f57a531b7598e892 Mon Sep 17 00:00:00 2001 From: beerosagos Date: Wed, 23 Aug 2023 11:46:25 +0200 Subject: [PATCH] chainhash: add support to legacy-marshaled hashes Recent commits 1d6e578 and 72ea23e introduced a change in the way Hashes are serialized and deserialized. This change could cause errors in downstream applications that persisted hashes serialized using the previous methods. This introduces support for legacy-serialized hashes unmarshaling and restores the compatibility with previous versions. --- chaincfg/chainhash/hash.go | 20 ++++++++++++++++++++ chaincfg/chainhash/hash_test.go | 10 ++++++++++ 2 files changed, 30 insertions(+) diff --git a/chaincfg/chainhash/hash.go b/chaincfg/chainhash/hash.go index fc059787db..4aa7aeb64c 100644 --- a/chaincfg/chainhash/hash.go +++ b/chaincfg/chainhash/hash.go @@ -118,6 +118,12 @@ func (hash Hash) MarshalJSON() ([]byte, error) { // UnmarshalJSON parses the hash with JSON appropriate string value. func (hash *Hash) UnmarshalJSON(input []byte) error { + // If the first byte indicates an array, the hash could have been marshalled + // using the legacy method and e.g. persisted. + if len(input) > 0 && input[0] == '[' { + return decodeLegacy(hash, input) + } + var sh string err := json.Unmarshal(input, &sh) if err != nil { @@ -217,3 +223,17 @@ func Decode(dst *Hash, src string) error { return nil } + +// decodeLegacy decodes an Hash that has been encoded with the legacy method +// (i.e. represented as a bytes array) to a destination. +func decodeLegacy(dst *Hash, src []byte) error { + var hashBytes []byte + err := json.Unmarshal(src, &hashBytes) + if err != nil { + return err + } + if len(hashBytes) != HashSize { + return ErrHashStrSize + } + return dst.SetBytes(hashBytes) +} diff --git a/chaincfg/chainhash/hash_test.go b/chaincfg/chainhash/hash_test.go index 19f34e3a93..85738a66c3 100644 --- a/chaincfg/chainhash/hash_test.go +++ b/chaincfg/chainhash/hash_test.go @@ -199,6 +199,7 @@ func TestNewHashFromStr(t *testing.T) { // TestHashJsonMarshal tests json marshal and unmarshal. func TestHashJsonMarshal(t *testing.T) { hashStr := "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506" + legacyHashStr := []byte("[6,229,51,253,26,218,134,57,31,63,108,52,50,4,176,210,120,212,170,236,28,11,32,170,39,186,3,0,0,0,0,0]") hash, err := NewHashFromStr(hashStr) if err != nil { @@ -219,4 +220,13 @@ func TestHashJsonMarshal(t *testing.T) { if !hash.IsEqual(&newHash) { t.Errorf("String: wrong hash string - got %v, want %v", newHash.String(), hashStr) } + + err = newHash.UnmarshalJSON(legacyHashStr) + if err != nil { + t.Errorf("Unmarshal legacy json error:%v, hash:%v", err, legacyHashStr) + } + + if !hash.IsEqual(&newHash) { + t.Errorf("String: wrong hash string - got %v, want %v", newHash.String(), hashStr) + } }