mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-23 13:41:37 +00:00
core: add cache to native Policy contract
We can cache maxBlockSize, maxTransactionsPerBlock and feePerByte in order to reduce the number of storage requests.
This commit is contained in:
parent
08cc04c3d5
commit
c2735a4569
2 changed files with 60 additions and 0 deletions
|
@ -640,6 +640,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
|||
bc.lock.Unlock()
|
||||
return err
|
||||
}
|
||||
bc.contracts.Policy.OnPersistEnd(bc.dao)
|
||||
bc.topBlock.Store(block)
|
||||
atomic.StoreUint32(&bc.blockHeight, block.Index)
|
||||
bc.memPool.RemoveStale(bc.isTxStillRelevant, bc)
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/binary"
|
||||
"math/big"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
|
@ -42,6 +43,14 @@ var (
|
|||
// Policy represents Policy native contract.
|
||||
type Policy struct {
|
||||
interop.ContractMD
|
||||
lock sync.RWMutex
|
||||
// isValid defies whether cached values were changed during the current
|
||||
// consensus iteration. If false, these values will be updated after
|
||||
// blockchain DAO persisting. If true, we can safely use cached values.
|
||||
isValid bool
|
||||
maxTransactionsPerBlock uint32
|
||||
maxBlockSize uint32
|
||||
feePerByte int64
|
||||
}
|
||||
|
||||
var _ interop.Contract = (*Policy)(nil)
|
||||
|
@ -135,6 +144,12 @@ func (p *Policy) Initialize(ic *interop.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.isValid = true
|
||||
p.maxTransactionsPerBlock = defaultMaxTransactionsPerBlock
|
||||
p.maxBlockSize = defaultMaxBlockSize
|
||||
p.feePerByte = defaultFeePerByte
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -143,6 +158,26 @@ func (p *Policy) OnPersist(ic *interop.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// OnPersistEnd updates cached Policy values if they've been changed
|
||||
func (p *Policy) OnPersistEnd(dao dao.DAO) {
|
||||
if p.isValid {
|
||||
return
|
||||
}
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
maxTxPerBlock := p.getUint32WithKey(dao, maxTransactionsPerBlockKey)
|
||||
p.maxTransactionsPerBlock = maxTxPerBlock
|
||||
|
||||
maxBlockSize := p.getUint32WithKey(dao, maxBlockSizeKey)
|
||||
p.maxBlockSize = maxBlockSize
|
||||
|
||||
feePerByte := p.getInt64WithKey(dao, feePerByteKey)
|
||||
p.feePerByte = feePerByte
|
||||
|
||||
p.isValid = true
|
||||
}
|
||||
|
||||
// getMaxTransactionsPerBlock is Policy contract method and returns the upper
|
||||
// limit of transactions per block.
|
||||
func (p *Policy) getMaxTransactionsPerBlock(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
|
||||
|
@ -152,11 +187,21 @@ func (p *Policy) getMaxTransactionsPerBlock(ic *interop.Context, _ []stackitem.I
|
|||
// GetMaxTransactionsPerBlockInternal returns the upper limit of transactions per
|
||||
// block.
|
||||
func (p *Policy) GetMaxTransactionsPerBlockInternal(dao dao.DAO) uint32 {
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
if p.isValid {
|
||||
return p.maxTransactionsPerBlock
|
||||
}
|
||||
return p.getUint32WithKey(dao, maxTransactionsPerBlockKey)
|
||||
}
|
||||
|
||||
// getMaxBlockSize is Policy contract method and returns maximum block size.
|
||||
func (p *Policy) getMaxBlockSize(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
if p.isValid {
|
||||
return stackitem.NewBigInteger(big.NewInt(int64(p.maxBlockSize)))
|
||||
}
|
||||
return stackitem.NewBigInteger(big.NewInt(int64(p.getUint32WithKey(ic.DAO, maxBlockSizeKey))))
|
||||
}
|
||||
|
||||
|
@ -168,6 +213,11 @@ func (p *Policy) getFeePerByte(ic *interop.Context, _ []stackitem.Item) stackite
|
|||
|
||||
// GetFeePerByteInternal returns required transaction's fee per byte.
|
||||
func (p *Policy) GetFeePerByteInternal(dao dao.DAO) int64 {
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
if p.isValid {
|
||||
return p.feePerByte
|
||||
}
|
||||
return p.getInt64WithKey(dao, feePerByteKey)
|
||||
}
|
||||
|
||||
|
@ -205,10 +255,13 @@ func (p *Policy) setMaxTransactionsPerBlock(ic *interop.Context, args []stackite
|
|||
return stackitem.NewBool(false)
|
||||
}
|
||||
value := uint32(toBigInt(args[0]).Int64())
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
err = p.setUint32WithKey(ic.DAO, maxTransactionsPerBlockKey, value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
p.isValid = false
|
||||
return stackitem.NewBool(true)
|
||||
}
|
||||
|
||||
|
@ -225,10 +278,13 @@ func (p *Policy) setMaxBlockSize(ic *interop.Context, args []stackitem.Item) sta
|
|||
if payload.MaxSize <= value {
|
||||
return stackitem.NewBool(false)
|
||||
}
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
err = p.setUint32WithKey(ic.DAO, maxBlockSizeKey, value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
p.isValid = false
|
||||
return stackitem.NewBool(true)
|
||||
}
|
||||
|
||||
|
@ -242,10 +298,13 @@ func (p *Policy) setFeePerByte(ic *interop.Context, args []stackitem.Item) stack
|
|||
return stackitem.NewBool(false)
|
||||
}
|
||||
value := toBigInt(args[0]).Int64()
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
err = p.setInt64WithKey(ic.DAO, feePerByteKey, value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
p.isValid = false
|
||||
return stackitem.NewBool(true)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue