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 <shaleva.ann@nspcc.ru>
This commit is contained in:
Anna Shaleva 2023-04-26 14:10:12 +03:00
parent 2c984e2393
commit d560395985
2 changed files with 21 additions and 13 deletions

View file

@ -2447,7 +2447,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)
}
@ -2852,11 +2855,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.

View file

@ -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) {
@ -1952,11 +1950,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) {