From 67d4d891ef847a8979fce36a37073ff4d74316b6 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 26 Apr 2023 14:10:12 +0300 Subject: [PATCH] core: prevent direct access to Notary contract if not active Otherwise it will cause panic, which isn't expected behaviour. Signed-off-by: Anna Shaleva --- pkg/core/blockchain.go | 14 ++++++++++---- pkg/core/blockchain_neotest_test.go | 20 +++++++++++--------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 064453ca5..67c6f8b9e 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -2567,7 +2567,10 @@ func (bc *Blockchain) verifyTxAttributes(d *dao.Simple, tx *transaction.Transact nvb := tx.Attributes[i].Value.(*transaction.NotValidBefore).Height curHeight := bc.BlockHeight() if isPartialTx { - maxNVBDelta := bc.contracts.Notary.GetMaxNotValidBeforeDelta(bc.dao) + maxNVBDelta, err := bc.GetMaxNotValidBeforeDelta() + if err != nil { + return fmt.Errorf("%w: failed to retrieve MaxNotValidBeforeDelta value from native Notary contract: %v", ErrInvalidAttribute, err) + } if curHeight+maxNVBDelta < nvb { return fmt.Errorf("%w: NotValidBefore (%d) bigger than MaxNVBDelta (%d) allows at height %d", ErrInvalidAttribute, nvb, maxNVBDelta, curHeight) } @@ -2972,11 +2975,14 @@ func (bc *Blockchain) GetMaxVerificationGAS() int64 { } // GetMaxNotValidBeforeDelta returns maximum NotValidBeforeDelta Notary limit. -func (bc *Blockchain) GetMaxNotValidBeforeDelta() uint32 { +func (bc *Blockchain) GetMaxNotValidBeforeDelta() (uint32, error) { if !bc.config.P2PSigExtensions { - panic("disallowed call to Notary") + panic("disallowed call to Notary") // critical error, thus panic. } - return bc.contracts.Notary.GetMaxNotValidBeforeDelta(bc.dao) + if bc.contracts.Notary.Metadata().UpdateHistory[0] > bc.BlockHeight() { + return 0, fmt.Errorf("native Notary is active starting from %d", bc.contracts.Notary.Metadata().UpdateHistory[0]) + } + return bc.contracts.Notary.GetMaxNotValidBeforeDelta(bc.dao), nil } // GetStoragePrice returns current storage price. diff --git a/pkg/core/blockchain_neotest_test.go b/pkg/core/blockchain_neotest_test.go index f5e2edcbf..3e64fadd5 100644 --- a/pkg/core/blockchain_neotest_test.go +++ b/pkg/core/blockchain_neotest_test.go @@ -347,10 +347,9 @@ func TestBlockchain_InitializeNativeCacheWrtNativeActivations(t *testing.T) { e = neotest.NewExecutor(t, bc, validators, committee) h := e.Chain.BlockHeight() - // Notary isn't initialized yet, so accessing Notary cache should panic. - require.Panics(t, func() { - _ = e.Chain.GetMaxNotValidBeforeDelta() - }) + // Notary isn't initialized yet, so accessing Notary cache should return error. + _, err = e.Chain.GetMaxNotValidBeforeDelta() + require.Error(t, err) // Ensure Notary will be properly initialized and accessing Notary cache works // as expected. @@ -359,9 +358,8 @@ func TestBlockchain_InitializeNativeCacheWrtNativeActivations(t *testing.T) { e.AddNewBlock(t) }, h+uint32(i)+1) } - require.NotPanics(t, func() { - _ = e.Chain.GetMaxNotValidBeforeDelta() - }) + _, err = e.Chain.GetMaxNotValidBeforeDelta() + require.NoError(t, err) } func TestBlockchain_AddHeaders(t *testing.T) { @@ -1949,11 +1947,15 @@ func TestBlockchain_VerifyTx(t *testing.T) { require.Error(t, bc.PoolTxWithData(tx, 5, mp, bc, verificationF)) }) t.Run("bad NVB: too big", func(t *testing.T) { - tx := getPartiallyFilledTx(bc.BlockHeight()+bc.GetMaxNotValidBeforeDelta()+1, bc.BlockHeight()+1) + maxNVB, err := bc.GetMaxNotValidBeforeDelta() + require.NoError(t, err) + tx := getPartiallyFilledTx(bc.BlockHeight()+maxNVB+1, bc.BlockHeight()+1) require.True(t, errors.Is(bc.PoolTxWithData(tx, 5, mp, bc, verificationF), core.ErrInvalidAttribute)) }) t.Run("bad ValidUntilBlock: too small", func(t *testing.T) { - tx := getPartiallyFilledTx(bc.BlockHeight(), bc.BlockHeight()+bc.GetMaxNotValidBeforeDelta()+1) + maxNVB, err := bc.GetMaxNotValidBeforeDelta() + require.NoError(t, err) + tx := getPartiallyFilledTx(bc.BlockHeight(), bc.BlockHeight()+maxNVB+1) require.True(t, errors.Is(bc.PoolTxWithData(tx, 5, mp, bc, verificationF), core.ErrInvalidAttribute)) }) t.Run("good", func(t *testing.T) {