core: add cache to Policy blocked accounts

Close #1441
This commit is contained in:
Anna Shaleva 2020-10-06 12:00:42 +03:00
parent 2ea29924c4
commit 9fe2b04db9
2 changed files with 30 additions and 3 deletions

View file

@ -655,7 +655,9 @@ func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error
bc.lock.Unlock() bc.lock.Unlock()
return err return err
} }
bc.contracts.Policy.OnPersistEnd(bc.dao) if err := bc.contracts.Policy.OnPersistEnd(bc.dao); err != nil {
return fmt.Errorf("failed to call OnPersistEnd for Policy native contract: %w", err)
}
if err := bc.contracts.Designate.OnPersistEnd(bc.dao); err != nil { if err := bc.contracts.Designate.OnPersistEnd(bc.dao); err != nil {
return err return err
} }

View file

@ -17,6 +17,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/network/payload" "github.com/nspcc-dev/neo-go/pkg/network/payload"
"github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
) )
@ -63,6 +64,7 @@ type Policy struct {
feePerByte int64 feePerByte int64
maxBlockSystemFee int64 maxBlockSystemFee int64
maxVerificationGas int64 maxVerificationGas int64
blockedAccounts BlockedAccounts
} }
var _ interop.Contract = (*Policy)(nil) var _ interop.Contract = (*Policy)(nil)
@ -182,6 +184,7 @@ func (p *Policy) Initialize(ic *interop.Context) error {
p.feePerByte = defaultFeePerByte p.feePerByte = defaultFeePerByte
p.maxBlockSystemFee = defaultMaxBlockSystemFee p.maxBlockSystemFee = defaultMaxBlockSystemFee
p.maxVerificationGas = defaultMaxVerificationGas p.maxVerificationGas = defaultMaxVerificationGas
p.blockedAccounts = make([]util.Uint160, 0)
return nil return nil
} }
@ -192,9 +195,9 @@ func (p *Policy) OnPersist(ic *interop.Context) error {
} }
// OnPersistEnd updates cached Policy values if they've been changed // OnPersistEnd updates cached Policy values if they've been changed
func (p *Policy) OnPersistEnd(dao dao.DAO) { func (p *Policy) OnPersistEnd(dao dao.DAO) error {
if p.isValid { if p.isValid {
return return nil
} }
p.lock.Lock() p.lock.Lock()
defer p.lock.Unlock() defer p.lock.Unlock()
@ -213,7 +216,18 @@ func (p *Policy) OnPersistEnd(dao dao.DAO) {
p.maxVerificationGas = defaultMaxVerificationGas p.maxVerificationGas = defaultMaxVerificationGas
si := dao.GetStorageItem(p.ContractID, blockedAccountsKey)
if si == nil {
return errors.New("BlockedAccounts uninitialized")
}
ba, err := BlockedAccountsFromBytes(si.Value)
if err != nil {
return fmt.Errorf("failed to decode BlockedAccounts from bytes: %w", err)
}
p.blockedAccounts = ba
p.isValid = true p.isValid = true
return nil
} }
// getMaxTransactionsPerBlock is Policy contract method and returns the upper // getMaxTransactionsPerBlock is Policy contract method and returns the upper
@ -300,6 +314,11 @@ func (p *Policy) getBlockedAccounts(ic *interop.Context, _ []stackitem.Item) sta
// GetBlockedAccountsInternal returns list of blocked accounts hashes. // GetBlockedAccountsInternal returns list of blocked accounts hashes.
func (p *Policy) GetBlockedAccountsInternal(dao dao.DAO) (BlockedAccounts, error) { func (p *Policy) GetBlockedAccountsInternal(dao dao.DAO) (BlockedAccounts, error) {
p.lock.RLock()
defer p.lock.RUnlock()
if p.isValid {
return p.blockedAccounts, nil
}
si := dao.GetStorageItem(p.ContractID, blockedAccountsKey) si := dao.GetStorageItem(p.ContractID, blockedAccountsKey)
if si == nil { if si == nil {
return nil, errors.New("BlockedAccounts uninitialized") return nil, errors.New("BlockedAccounts uninitialized")
@ -434,12 +453,15 @@ func (p *Policy) blockAccount(ic *interop.Context, args []stackitem.Item) stacki
copy(ba[indexToInsert+1:], ba[indexToInsert:]) copy(ba[indexToInsert+1:], ba[indexToInsert:])
ba[indexToInsert] = value ba[indexToInsert] = value
} }
p.lock.Lock()
defer p.lock.Unlock()
err = ic.DAO.PutStorageItem(p.ContractID, blockedAccountsKey, &state.StorageItem{ err = ic.DAO.PutStorageItem(p.ContractID, blockedAccountsKey, &state.StorageItem{
Value: ba.Bytes(), Value: ba.Bytes(),
}) })
if err != nil { if err != nil {
panic(err) panic(err)
} }
p.isValid = false
return stackitem.NewBool(true) return stackitem.NewBool(true)
} }
@ -469,12 +491,15 @@ func (p *Policy) unblockAccount(ic *interop.Context, args []stackitem.Item) stac
return stackitem.NewBool(false) return stackitem.NewBool(false)
} }
ba = append(ba[:indexToRemove], ba[indexToRemove+1:]...) ba = append(ba[:indexToRemove], ba[indexToRemove+1:]...)
p.lock.Lock()
defer p.lock.Unlock()
err = ic.DAO.PutStorageItem(p.ContractID, blockedAccountsKey, &state.StorageItem{ err = ic.DAO.PutStorageItem(p.ContractID, blockedAccountsKey, &state.StorageItem{
Value: ba.Bytes(), Value: ba.Bytes(),
}) })
if err != nil { if err != nil {
panic(err) panic(err)
} }
p.isValid = false
return stackitem.NewBool(true) return stackitem.NewBool(true)
} }