diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index c778a136b..4f7940a3c 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -381,6 +381,7 @@ func (bc *Blockchain) init() error { P2PSigExtensions: bc.config.P2PSigExtensions, P2PStateExchangeExtensions: bc.config.P2PStateExchangeExtensions, KeepOnlyLatestState: bc.config.Ledger.KeepOnlyLatestState, + Magic: uint32(bc.config.Magic), Value: version, } bc.dao.PutVersion(ver) @@ -415,6 +416,10 @@ func (bc *Blockchain) init() error { return fmt.Errorf("KeepOnlyLatestState setting mismatch (old=%v, new=%v)", ver.KeepOnlyLatestState, bc.config.Ledger.KeepOnlyLatestState) } + if ver.Magic != uint32(bc.config.Magic) { + return fmt.Errorf("protocol configuration Magic mismatch (old=%v, new=%v)", + ver.Magic, bc.config.Magic) + } bc.dao.Version = ver bc.persistent.Version = ver diff --git a/pkg/core/blockchain_neotest_test.go b/pkg/core/blockchain_neotest_test.go index cacfe126c..f71b8890b 100644 --- a/pkg/core/blockchain_neotest_test.go +++ b/pkg/core/blockchain_neotest_test.go @@ -141,6 +141,15 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) { require.Error(t, err) require.True(t, strings.Contains(err.Error(), "KeepOnlyLatestState setting mismatch"), err) }) + t.Run("Magic mismatch", func(t *testing.T) { + ps = newPS(t) + _, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.Blockchain) { + customConfig(c) + c.Magic = 100500 + }, ps) + require.Error(t, err) + require.True(t, strings.Contains(err.Error(), "protocol configuration Magic mismatch"), err) + }) t.Run("corrupted headers", func(t *testing.T) { ps = newPS(t) diff --git a/pkg/core/dao/dao.go b/pkg/core/dao/dao.go index 844490dd0..54a9cd85a 100644 --- a/pkg/core/dao/dao.go +++ b/pkg/core/dao/dao.go @@ -440,6 +440,7 @@ type Version struct { P2PSigExtensions bool P2PStateExchangeExtensions bool KeepOnlyLatestState bool + Magic uint32 Value string } @@ -464,7 +465,7 @@ func (v *Version) FromBytes(data []byte) error { return nil } - if len(data) != i+3 { + if len(data) < i+3 { return errors.New("version is invalid") } @@ -474,6 +475,11 @@ func (v *Version) FromBytes(data []byte) error { v.P2PSigExtensions = data[i+2]&p2pSigExtensionsBit != 0 v.P2PStateExchangeExtensions = data[i+2]&p2pStateExchangeExtensionsBit != 0 v.KeepOnlyLatestState = data[i+2]&keepOnlyLatestStateBit != 0 + + m := i + 3 + if len(data) == m+4 { + v.Magic = binary.LittleEndian.Uint32(data[m:]) + } return nil } @@ -492,7 +498,9 @@ func (v *Version) Bytes() []byte { if v.KeepOnlyLatestState { mask |= keepOnlyLatestStateBit } - return append([]byte(v.Value), '\x00', byte(v.StoragePrefix), mask) + res := append([]byte(v.Value), '\x00', byte(v.StoragePrefix), mask, 0, 0, 0, 0) + binary.LittleEndian.PutUint32(res[len(res)-4:], v.Magic) + return res } func (dao *Simple) mkKeyPrefix(k storage.KeyPrefix) []byte {